我有一个1000x1500像素位图,我想在Android中制作一个可变副本。
当我运行以下代码时......
// int width = original.getWidth(); // 1000px
// int height = original.getHeight(); // 1500px
final Bitmap result = original.copy(original.getConfig(), true);
original.recycle();
...我在OutOfMemoryError
行找到了copy
:
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
ERROR/GraphicsJNI(419): VM won't let us allocate 6000000 bytes
为什么复制指令对于1000x1500像素位图需要 6MB (!)?
如何以更高效的内存方式从非可变位图创建可变位图?
BitmapFactory返回不可变位图。显然,从不可变位图创建可变位图的唯一方法是将其复制到新的可变位图中。对于1000x1500位图,这显然需要 12MB (1000x1500x4x2),这会导致大多数Android设备出现OutOfMemoryError。
这个问题在Android中无法解决吗?
答案 0 :(得分:5)
回答你的第一个问题:
1000 * 1500 * 32/8 = 600万
(32位/像素的颜色信息)
要回答第二个问题:您需要通过以块为单位处理图像来缩小图像的大小,或者降低分辨率或颜色深度。
答案 1 :(得分:5)
cdonner让我朝着正确的方向前进。
原来,位图使用的是 ARGB_8888 ,每个像素需要32位,并且比这个特定应用所需的更多。
将位图config更改为 RGB_565 (每像素需要16位),可将内存消耗减少一半。
答案 2 :(得分:4)
有一个棘手的解决方法,我曾经避免使用OutOfMemoryError。 我注册了一个接收器,以便它在不同的过程中运行:
<receiver android:name=".ImageTransformReceiver"
android:exported="true" android:process=":imageTransformProcess"/>
在接收器内部,我执行昂贵的内存操作(加载两个大图像并将它们合并为一个)。我将结果图像写入文件,并将广播发送回主进程,参考Intent中的结果图像文件路径。
这只是一个允许您在一个应用程序中使用更多操作系统内存的黑客攻击。希望这会有所帮助。
答案 3 :(得分:2)
从API级别开始,11 BitmapFactory.Options有一个布尔'inMutable',可以设置为生成可变位图。
虽然这不会改变单个位图的内存使用,但它将使您不必在内存中存储两个副本。