p-lr / MapView

A Fast, memory efficient Android library to display tiled maps, with support for markers, paths, and rotation.
Apache License 2.0
184 stars 38 forks source link

bitmap marked for reuse can't fit new bitmap error (100% reproducible) for Remote HTTP mapview #40

Closed kuromimi closed 1 year ago

kuromimi commented 1 year ago

Hello, With the code below (modified based on RemoteHttpFragment.kt), I got bitmap load error:

URL:https://cyberjapandata.gsi.go.jp/xyz/std/4/3/5.png bitmap marked for reuse (131072 bytes) can't fit new bitmap (524288 bytes)

As the screenshot, the mid center of the US continental failed to load. I am using MapView3.4.1. Any thoughts?

Screenshot_1666659045

        val tileStreamProvider = object : TileStreamProvider {
            override fun getTileStream(row: Int, col: Int, zoomLvl: Int): InputStream? {
                return try {
//                    val url = URL("https://plrapps.ovh:8080/mapview-tile/$zoomLvl/$row/$col.jpg")
                    val url = URL("https://cyberjapandata.gsi.go.jp/xyz/std/$zoomLvl/$col/$row.png")
Log.d("DDD","URL:"+url)
                    val connection = createConnection(url)
                    connection.connect()
                    BufferedInputStream(connection.inputStream)
                } catch (e: Exception) {
                    null
                }
            }

            fun createConnection(url: URL): HttpURLConnection {
                val connection = url.openConnection() as HttpURLConnection
                connection.doInput = true
                return connection
            }
        }
        val tileSize = 256
        val MAX_ZOOM = 5
        var zoomLevelScale = FloatArray(MAX_ZOOM + 1)
        var scale = 1f
        for (i in MAX_ZOOM downTo 0) {
            zoomLevelScale[i] = scale
            scale = scale / 2
        }

        val config = MapViewConfiguration(
                MAX_ZOOM+1,     // no level=1 map; need plus one level
                8192, 8192, tileSize, tileStreamProvider
        ).setMaxScale(2f).setPadding(tileSize * 2).setWorkerCount(1)
        .setStartScale(zoomLevelScale[4])

        mapView.configure(config)
        mapView.scale = zoomLevelScale[4]
}
p-lr commented 1 year ago

This usually happens when some tiles have different (higher) quality settings. This library is designed to reuse the memory allocated for bitmaps, but this works as long as all bitmaps require the same amount of memory (or, in other words, have the same quality settings). I would refer to this issue. Even though this about another library, the idea is the same.

kuromimi commented 1 year ago

Pierre, Thank you for the comment. The map data is owned by Geospatial Information Authority of Japan; no chance to update data. OK, closing the topic.

p-lr commented 1 year ago

In this case, I've thought of a way to not use Bitmap reuse when this kind of issue happens. This is less performant but better than what we have now. I've pushed the change in the branch try-fix-#40. As per my tests, it fixes your issue. If you can confirm, I can make a new version with that change.

kuromimi commented 1 year ago

Pierre, Thanks for the update. Tried the change with scroll/zoom-in/out on the map config having more zoom level (max=17). I confirmed no map block failed to load at all! I still see the warning message, but it is because of reload. Understood.

D URL http://cyberjapandata.gsi.go.jp/xyz/std/8/227/102.png W bitmap marked for reuse (131072 bytes) can't fit new bitmap (262144 bytes) D URL http://cyberjapandata.gsi.go.jp/xyz/std/8/227/102.png

I see those reloads on worldmap only (level < 9); reloading shouldnot be much of a problem on actual use case, I think. Thank you for the fix!

p-lr commented 1 year ago

Alright! The new 3.1.5 version should be available on maven soon. Thanks for the feedback.