3

我在磁盘上有 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 时。

4

2 回答 2

2

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

如果您注意文档,它会说选项用于 inSampleSize,这似乎确实有效,但没有特别提到 inPreferredConfig 和 inBitmap 的使用。我想这意味着尊重 inPreferredConfig 和 inBitmap 取决于制造商或在 4.1+ 中添加。

于 2012-12-14T03:32:15.977 回答
1

你在回收recycleBitmap吗?

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

于 2012-11-26T18:29:26.500 回答