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.
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+.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With