Displaying huge bitmaps on Android Canvas Efficiently

Hello guys again!

My last post was about displaying huge bitmaps on Android canvas inefficiently but so that it would at least work.

I initially thought that BitmapRegionDecoder would load the bitmaps outside of the vm heap, but god was I wrong!

After writing the post and at the night I was testing the app I am still working on I rotated the screen and oh my, it crashed.

I thought it could be something general that was going wrong when bundling up the data to be used after activity is recreated but no, when I got on computer I found out it was the OutOfMemory which was the initial problem which leaded me to chunk up the data.

Instead of writing some code to flush the memory on the rotate, I thought if I could do it good at once!

As I mentioned on my last post, the best use of BitmapRegionDecoder would be to only load area that’s visible, or area that’s big enough to let you move on the bitmap a bit before long wait time of reloading a new chunk of the image.

The idea of this was hard in my mind but after a little brainwork I figured how I should do it!

On my “HugeImageView” when user scrolls the screen it changes the x and y offset according to the distance that the touch travelled and the scale factor of the screen.

then it calls updateMatrix() which basically performs the operations on matrix

resulting with a matrix that can be used to draw on the screen

on the same method I also store the inverse of the drawing matrix to inverseMatrix

then I calculate the visible area of the screen and visible area of the bitmap(I’ll soon tell you why I am storing both of them)

and then we get to the goodies, I check if the loadedArea which is basically the area that’s loaded in memory doesn’t contain the area of bitmap that’s visible to the viewer

and if it isn’t I’ll calculateBestLoadedArea() which basically calculates the best possible area that could be loaded in order to let the user move a little before having to reload bitmap..

I was thinking of adding the direction of drag in the calculation because its most likely that the user will continue to drag in that direction.

and then I execute AsyncTask which loads the “loadingRect” and after its loaded it’ll redraw the screen so user will see the new bitmap

And to make this as friendly as the user as possible and to avoid random flickering on the screen I am always on start of each frame drawing a black screen

and this is what I need the visible screen area for!

Then I am drawing the loading text repeated and with white background

and only then I draw the loaded area!

Whats next?

As I mentioned before, scrolling direction prediction should be added
Also it would be good to also load nearby bitmap regions if there’s enough memory

Currently I am myself keeping the lastly used bitmaps/regions weakreferenced so when region is changed I can check the list if the reference is still there and show that instead of totally reloading it from disk!

If you got optimization ideas or such please leave a comment :)

Indie game developer / programmer from Finland

Posted in Uncategorized

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">