2012-11-20 30 views
3

我在磁盘上有1280x1280 JPG,我使用下面的代码来解码图像的一个区域(裁剪两侧)以显示在ImageView中。在剪切图像的顶部和底部时存在类似的问题。为什么BitmapRegionDecoder分配这么多内存?

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; 
} 

在一个宏基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), [email protected] 
    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;似乎否定了Xoom上的第二次分配,就好像位图被正确回收,但仍有为解码器分配的内存。

使用完整图像(1280x1280)和BitmapFactory进行回收的工作方式虽然使用的存储整个图像的内存要比区域要求的要多得多。

我不明白为什么Xoom不能正常工作,但宏碁很好,当他们都运行Android 4.0.x.

+0

...? (只是检查) – auval

+0

它看起来Xoom不会在GPU上执行解码/裁剪/编码 – auval

+0

@uval hardwareAccelerated设置为true,但不幸的是它没有什么区别,尽管您关于未在GPU上执行的操作的理论很有意义 –

回答

1

你在回收recycleBitmap吗?

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

+0

我没有在recycleBitmap上调用recycle,虽然我确实有代码比较两个对象身份的相等性,看是否重新使用位图。在Xoom上,有两个不同的对象,但回收结果是黑色的Bitmaps!在这种情况下,Xoom的另一个怪癖就是Nexus设备显示对象相等,因为内存被重新使用。 –

+0

我会尽我所能在Xoom上测试一下我的项目中的一些类似代码,然后回复给您。 –

2

我注意到我的爱可视G9 80(4.0.4)Bitmaps返回使用RGB8888,即使我要求RGB656。如果我解码一个1024x1024方块并在结果位图上调用getByteCount(),它将返回4MB。即使我使用RGB8888传递位图,它仍然会分配一个新的。

如果您注意到文档,它说选项用于inSampleSize,它似乎工作,但没有具体提及使用inPreferredConfig和inBitmap。我想这意味着尊重inPreferredConfig和inBitmap取决于制造商或添加到4.1 +。

+0

链接到某些来源可能会有所帮助。 – JSuar

+0

4444和656模式是“弃用”.. bitmapdecoder至少会吐在你最近的android版本8888总是。 now ..是否阻止了谷歌制作开发者指南和视频,他们说你可以通过使用它作为选项轻松地节省内存?当然不是。 –

相关问题