Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is BitmapRegionDecoder allocating so much memory?

I have 1280x1280 JPGs on disk and I'm using the following code to decode a region of the image (clipping off the sides) to display in an ImageView. There are similar issues in clipping the top and bottom off the image.

private Bitmap decodeBitmapRegion(InputStream in, Rect region, Bitmap recycleBitmap) {
    LOGD(TAG, "decodeBitmapRegion region=" + region + ", recycleBitmap=" + recycleBitmap );

    Bitmap bitmap = null;
    BitmapRegionDecoder decoder = null;

    BitmapFactory.Options options = new BitmapFactory.Options();        
    options.inSampleSize = 1;
    options.inBitmap = recycleBitmap;

    try {
        decoder = BitmapRegionDecoder.newInstance(in, false);
        bitmap = decoder.decodeRegion(region, options);
    } catch (IllegalArgumentException e){
        LOGE(TAG, "Failed to recycle bitmap for rect=" + region, e);
    } catch (IOException e) {
        LOGE(TAG, "Failed to decode into rect=" + region, e);
    } finally {
        if (decoder != null) decoder.recycle();
    }

    return bitmap;
}

On an Acer Iconia A100 (4.0.3) the code works perfectly and decodes the region into the recycle bitmap if provided, allocating no memory on the heap. The logcat has no GC or grow heap messages. It's also working correctly on a Nexus 7 running 4.2.0.

On a Motorola Xoom (4.0.4) the code generates the following logcat. The first dalvikvm-heap grow (4738256 bytes) is presumably for the BitmapRegionDecoder's data and the second (3603216 bytes) matches the amount of memory required to store the image (800x1126x4). There's also a skia error.

  8522    LocationImageLoader  D  decodeBitmapRegion region=Rect(240, 77 - 1040, 1203), recycleBitmap=android.graphics.Bitmap@415319a8
  8522               dalvikvm  D  GC_FOR_ALLOC freed 8213K, 28% free 22782K/31623K, paused 34ms
  8522          dalvikvm-heap  I  Grow heap (frag case) to 26.808MB for 4738256-byte allocation
  8522               dalvikvm  D  GC_CONCURRENT freed 6K, 14% free 27403K/31623K, paused 3ms+7ms
  8522                   skia  D  WARNING: One-shot allocator has already allocated (alloc count = 1)
  8522               dalvikvm  D  GC_FOR_ALLOC freed 0K, 14% free 27403K/31623K, paused 33ms
  8522          dalvikvm-heap  I  Grow heap (frag case) to 30.238MB for 3603216-byte allocation
  8522               dalvikvm  D  GC_FOR_ALLOC freed 0K, 3% free 30922K/31623K, paused 41ms

Setting options.inPreferredConfig = Bitmap.Config.RGB_565; seems to negate the second allocation on the Xoom, as if the bitmap is recycled correctly, but there's still memory allocated for the decoder.

Recycling with the full images (1280x1280) and BitmapFactory works though significantly more memory is used to store the full image than would be required by the region.

I can't understand why the Xoom doesn't work but the Acer is fine, when both are running Android 4.0.x.

like image 898
David Snabel-Caunt Avatar asked Mar 12 '26 05:03

David Snabel-Caunt


2 Answers

I've noticed on my Archos G9 80 (4.0.4) that the Bitmaps returned are using RGB8888, even though I requested RGB656. If I decode a 1024x1024 square and call getByteCount() on the resulting Bitmap, it returns 4MB. Even if I pass in a Bitmap using RGB8888, it still allocates a new one.

If you note the documentation, it says the the Options are used for inSampleSize, which does appear to work, but the use of inPreferredConfig and inBitmap are not specifically mentioned. I guess that means honoring inPreferredConfig and inBitmap is up to the manufacturer or was added in 4.1+.

like image 179
Dustin Avatar answered Mar 14 '26 21:03

Dustin


Are you recycling the recycleBitmap?

Worth noting, that sometimes the recycled bitmap is the actual bitmap returned in some operations so you don't want to recycle it. However other times a new bitmap is instantiated in which case you want to recycle the original bitmap - Assuming it's no longer needed outside the scope of this method.

like image 23
Matt Gaunt Avatar answered Mar 14 '26 23:03

Matt Gaunt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!