Lee Han Kyeol
Lee Han Kyeol

Reputation: 2481

How to load Android Bitmap faster?

I'm creating an app which needs to show a series of Bitmaps of a video's frames. The app uses MediaCodec to decode a video into a number of frames and gets Bitmaps of each frame to display them on ImageView.

The problem is that each Bitmap's size is about 2~3MB (Frame size is 1280 x 720, the size of 720p video.) so that when the number of Bitmap is above 60~65, the app crashes due to the lack of memory. In order to avoid this problem I've been implementing the D tour algorithm which loads only Bitmaps that need to be displayed right now or soon. Basically I've been trying these methods.

1. Load all Bitmaps in advance.

It's fast enough to meet my need but as mentioned the app crashes when the number of Bitmaps exceed 60~65.

2. When extracting frames, save each frame into a JPEG file and load specific JPEGs into Bitmaps when needed.

I used BitmapFactory.decodeFile to load a Bitmap from a JPEG, but it was slow.

3. When extracting frames, save whole frames into an MJPEG file and load specific "frame" (technically the byte array) into Bitmaps when needed.

I thought if I load Bitmap from the byte array itself the performance might be better. So when extracting frames, I created another metadata file containing information of each frame's byte indices and used that information to load Bitmaps when needed. [BitmapFactory.decodeByteArray](http://developer.android.com/reference/android/graphics/BitmapFactory.html#decodeByteArray(byte[], int, int)) is used. I could see a slight improvement in speed but it is still insufficient.

What else can I try to boost up Bitmap loading in this situation?

Upvotes: 2

Views: 4842

Answers (2)

tom91136
tom91136

Reputation: 8962

For your algorithm, some libraries such as Glide and Picasso can handle that for you. As for the encoding/decoding speed, JPEG is probably your best bet at quickly flushing the Bitmap to disk because the file size is small and it could be backed by hardware.

Some things you can try

  1. If you have control over how the Bitmap is generated, use RGB565 to reduce memory consumption(up to 50% less memory becaue ARGB8888 is 32bit where as RGB565 is 16bit)
  2. Create a smaller image and then scale it up later
  3. Add android:largeHeap=true to manifest so you have memory to work with
  4. LRU caching for the bitmap, this has been implemented in Picasso's caching as well

If you want, manually compiling your jpeg library for your specific needs are possible but that would require non trivial work. Here's something you can test right now.

Upvotes: 3

nmio
nmio

Reputation: 798

You have a few options, and your caching idea is smart. Off the top of my mind, here are a few things to try:

  • Focus on why your images are so large. An image of that resolution should be able to be compressed smaller than 2 - 3 MB, and if its possible to encode the data into a more compressed image format, it will greatly reduce the memory footprint of your app and result in faster loading times
  • If the full resolution photo isn't always needed, you can try resizing it on-demand and then later, if the full resolution photo is needed, you can load that
  • Load images in the background so that when the user needs them, they are already there. This can be accomplished by extending your adapter and loading images in async tasks. There is a great example of this in the Google examples: http://developer.android.com/training/displaying-bitmaps/process-bitmap.html

Upvotes: 2

Related Questions