为什么BitmapRegionDecoder会分配如此多的内存?

时间:2012-11-20 15:08:51

标签: android bitmap bitmapfactory

我在磁盘上有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上正常工作。

在Motorola Xoom(4.0.4)上,代码生成以下logcat。第一个dalvikvm-heap增长(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不起作用,但当两者都运行Android 4.0.x时,Acer都没问题。

2 个答案:

答案 0 :(得分:2)

我注意到我的Archos G9 80(4.0.4)返回的Bitmaps正在使用RGB8888,即使我请求了RGB656。如果我解码1024x1024平方并在生成的位图上调用getByteCount(),则返回4MB。即使我使用RGB8888传入一个位图,它仍然会分配一个新的。

如果您注意到文档,则表示选项用于inSampleSize,它看似起作用,但没有特别提及inPreferredConfig和inBitmap的使用。我想这意味着尊重inPreferredConfig和inBitmap取决于制造商或在4.1 +中添加。

答案 1 :(得分:1)

您是在回收recycleBitmap吗?

值得注意的是,有时回收的位图是某些操作中返回的实际位图,因此您不想回收它。但是有时候会实例化一个新的位图,在这种情况下你想要回收原始的位图 - 假设它不再需要超出这个方法的范围。