我的磁盘上有 1280x1280 JPG,我正在使用以下代码解码图像区域(剪掉边)以显示在 ImageView 中。裁剪图像的顶部和底部也存在类似的问题。
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;
}
在 Acer Iconia A100 (4.0.3) 上,代码可以完美运行,并将该区域解码为回收位图(如果提供),不在堆上分配内存。 logcat 没有 GC 或增长堆消息。它也可以在运行 4.2.0 的 Nexus 7 上正常工作。
在摩托罗拉 Xoom (4.0.4) 上,代码生成以下 logcat。第一个 dalvikvm 堆增长(4738256 字节)大概是用于 BitmapRegionDecoder 的数据,第二个(3603216 字节)与存储图像 (800x1126x4) 所需的内存量相匹配。还有一个 skia 错误。
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
设置 options.inPreferredConfig = Bitmap.Config.RGB_565;似乎否定了 Xoom 上的第二次分配,就好像位图被正确回收了一样,但仍然为解码器分配了内存。
使用完整图像 (1280x1280) 和 BitmapFactory 进行回收虽然用于存储完整图像的内存比区域所需的内存多得多。
我不明白为什么 Xoom 不工作但 Acer 很好,当两者都运行 Android 4.0.x 时。
最佳答案
我注意到在我的 Archos G9 80 (4.0.4) 上返回的位图使用的是 RGB8888,尽管我请求的是 RGB656。如果我解码一个 1024x1024 的正方形并在生成的位图上调用 getByteCount(),它返回 4MB。即使我使用 RGB8888 传入一个位图,它仍然会分配一个新位图。
如果您注意到文档,它会说 Options 用于 inSampleSize,这似乎确实有效,但没有具体提及 inPreferredConfig 和 inBitmap 的使用。我想这意味着尊重 inPreferredConfig 和 inBitmap 取决于制造商或在 4.1+ 中添加。
关于android - 为什么 BitmapRegionDecoder 分配这么多内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13476105/