Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help needed for displaying single image from Remote #1

Closed
shriharsha-bhagwat opened this issue Nov 19, 2019 · 9 comments
Closed

Help needed for displaying single image from Remote #1

shriharsha-bhagwat opened this issue Nov 19, 2019 · 9 comments

Comments

@shriharsha-bhagwat
Copy link

shriharsha-bhagwat commented Nov 19, 2019

Thanks for the wonderful library. I have used old java tileview library and now happy to use improved Kotlin version of it. I need one help with respect to displaying of a single image from remote. I just have a single image of size 1200 * 900. I would like to display it with zooming enabled. How would i configure it without using deep-zoom map.
My image : http://androidbash.com/data/floor1.jpg
I tried following config and i am unable to load the map.
var tileSize = 1200
val config = MapViewConfiguration(
1, 1200, 900, tileSize, tileStreamProvider
).setMaxScale(4f).setPadding(tileSize * 2).setWorkerCount(16)

@p-lr
Copy link
Owner

p-lr commented Nov 19, 2019

First, you need to make a deep-zoom map from your 1200*900 image.
To do that, you can follow this tutorial.

Then, the configuration should be:

val tileSize = 256
val config = MapViewConfiguration(
            4, 1200, 900, tileSize, tileStreamProvider
        ).setMaxScale(2f).setPadding(tileSize * 2).setWorkerCount(16)

I've done it myself, I get 4 levels:
image

If you need more help don't hesitate.

@p-lr
Copy link
Owner

p-lr commented Nov 19, 2019

Then, you will have to define a TileStreamProvider. This is the component which knows how to fetch tiles. It's implementation depends on the location of the tiles (are they in the app assets, on internal memory, or on remote server).

Assuming you will want those tiles to be served by your http server which hosts your website, then this implementation could look like this:

val tileStreamProvider = object : TileStreamProvider {
            override fun getTileStream(row: Int, col: Int, zoomLvl: Int): InputStream? {
                return try {
                    val url = URL("http://androidbash.com/data/floor/$zoomLvl/$row/$col.jpg")
                    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
            }
        }

@shriharsha-bhagwat
Copy link
Author

Thanks for such a quick response. I really appreciate it.

Yes after creating deep zoom map it works perfectly. But Can i display the map/image without creating deep-zoom map i.e just with single image as in the above link?

I was doing it in Tileview old java version with following code :

    String encodedImage = imageData.getFile().getBody();
    String decodedString = Base64.decode(encodedImage, Base64.DEFAULT);
   
    tileView.setSize(1200, 900);
    tileView.addDetailLevel(1.000f, decodedString, 1200, 900);
    tileView.setMarkerAnchorPoints(-0.5f, -0.5f);
    tileView.setBitmapProvider(new BitmapProviderInternalStorage());
    tileView.setScaleLimits(0, 2f);

Is there something similar i can do in this?

@p-lr
Copy link
Owner

p-lr commented Nov 20, 2019

You have to "tile" your image somehow, as MapView (and also TileView in its latest version) only supports squared tiles, and your image is rectangular.
As an alternative, you can only take the last level (folder number 3), rename it to 0 and delete the others. Then, in your configuration:

val tileSize = 256
val config = MapViewConfiguration(
            1, 1200, 900, tileSize, tileStreamProvider
        ).setMaxScale(2f).setPadding(tileSize * 2)

Of course, your TileStreamProvider should be adapted.
This way, you will see your image only at its full resolution while still leveraging the benefits of MapView.

@shriharsha-bhagwat
Copy link
Author

shriharsha-bhagwat commented Nov 21, 2019

Yes you are right. I understood now. Also one last thing. If you know any sample for indoor map and navigation using tileview please provide a link.

Thanks for helping out. Great work :)

@p-lr
Copy link
Owner

p-lr commented Nov 21, 2019

An example of app using MapView is TrekMe (my own app).

But if your question was really about TileView, again TrekMe, but the trekadvisor branch. Indeed, I used TileView but recently switched the app to use MapView. To save you from looking for the needle in haystack, here's a direct link of a real life TileView usage in trekadvisor branch: https://github.com/peterLaurence/TrekMe/blob/431bf08c2b47e00e1b16288899386d288fd80249/app/src/main/java/com/peterlaurence/trekadvisor/menu/mapview/MapViewFragment.java#L461

@shriharsha-bhagwat
Copy link
Author

shriharsha-bhagwat commented Nov 22, 2019

Okay i observing something in demo project as well as in mine. In RemoteHttpFragment, it will load initially well (First Image).

Then if i go to background and come back (i.e onResume) it is not loading properly. (Second Image)

What do you think is the cause?
For now I have resolved it by modifying the initialization of mapView as done in MapPathsFragment.

Screenshot_20191122-095134

Screenshot_20191122-095142

@p-lr
Copy link
Owner

p-lr commented Nov 22, 2019

Good catch!
It's in fact a misuse of MapView, which I mistakenly did inside some of the demos. The MapMarkersFragment and MapPathFragment weren't affected though.

I updated the demos to show proper usage, and it's fixed now. The issue were that the configuration was done inside onStart(). But onStart is called everytime the app regains focus after being in background (it's called right before onResume).
So the existing MapView was reconfigured. And this is bad - by design, a MapView shoul'dnt be configured twice, or it should be destroyed by calling MapView.destroy(), then re-created and configured. The recommended way is to configure the MapView inside onCreate - see the updated demos for that.
If you absolutely need to configure after onCreate, I suggest you take a look at DeferredFragment.

So I updated the demo and added a safeguard in the library. If we configure the MapView multiple times, we get an IllegalStateException with a message indicating the problem. This safeguard will be shipped in the next version.

@shriharsha-bhagwat
Copy link
Author

shriharsha-bhagwat commented Nov 24, 2019

Thanks for such quick replies and such quick updates.

You can close the issue as it is fixed :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants