android - 为什么 BitmapRegionDecoder 分配这么多内存?

标签 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 上正常工作。

在摩托罗拉 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/

相关文章:

android - 如何在不使用 Intent 和选择器的情况下显示电子邮件共享选项列表?

android - 在方向更改时保存 UI - 如果保留 Fragment,onSaveInstanceState 无法按预期工作

android - 压缩自定义相机拍摄的图像大小

Android:使用 BitmapFactory.decodeStream(...) 和 Assets 文件夹时 PNG 透明度失败

java - Android BitmapFactory解码文件在它应该被调用之前被调用

android - 'gradlew.bat' 不被识别为内部或外部命令, native react

android - 将用户 ID 发送到 Google Analytics

actionscript-3 - 如何在不使用 BitmapData.draw() 的情况下快速旋转构成 BitmapData 的像素?

android - ImageView 内存泄漏 - 简单图像

android - 如何在不影响位图大小的情况下降低位图质量