Android 中缩放图像会导致 OutOfMemory 异常
我正在开发一款由许多图像作为精灵组成的 Android 游戏。
当我按以下方式加载图像时:
public static Bitmap loadBitmap(int resId) {
return BitmapFactory.decodeResource(getResources(), resId, options);
}
一切都工作得很好。
当我尝试使用以下代码缩小或放大位图时:
public static Bitmap loadBitmap(int resId) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId, options);
Matrix matrix = new Matrix();
matrix.postScale(0.8f, 0.8f);
Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
bitmap = null;
return scaledBitmap;
}
应用程序崩溃并出现以下异常:
2211840-byte external allocation too large for this process.
Out of memory: Heap Size=4935KB, Allocated=2549KB, Bitmap Size=18463KB
VM won't let us allocate 2211840 bytes
为什么缩放会导致 OutOfMemory 异常?我什至尝试回收原始图像以节省一些空间。我不是故意使用 Bitmap.createScaledBitmap(...) 的,因为此方法会在内部发生内存泄漏(如其他在线资源中所述)。
预先感谢您,
兹拉特科
I'm developing an Android game consisting of many images as sprites.
When I load the images the following way:
public static Bitmap loadBitmap(int resId) {
return BitmapFactory.decodeResource(getResources(), resId, options);
}
everything works perfectly fine.
When I try to down-scale or up-scale the bitmap with this code:
public static Bitmap loadBitmap(int resId) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId, options);
Matrix matrix = new Matrix();
matrix.postScale(0.8f, 0.8f);
Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
bitmap.recycle();
bitmap = null;
return scaledBitmap;
}
the application crashes with the following exception:
2211840-byte external allocation too large for this process.
Out of memory: Heap Size=4935KB, Allocated=2549KB, Bitmap Size=18463KB
VM won't let us allocate 2211840 bytes
Why is the scaling causing OutOfMemory exception? I even try to recycle the original image in order to save some space. I'm not using Bitmap.createScaledBitmap(...)
intentionally, since this method does memory leaking internally (as explained in other online resources).
Thank you in advance,
Zlatko
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可能非常接近内存限制。看起来您正在创建一个相当大的位图(我不确定为什么您要使其与原始位图大小相同)。从日志中可以看出,您已经使用了 25MB 的 Java 分配和 18MB 的位图分配,因此您基本上已经达到了 48MB 堆限制。
另外我认为 createScaledBitmap() 泄漏的可能性很小。它所做的一切基本上就是您在这里所做的。
You are probably just very close to the memory limit. It looks like you are creating a pretty large bitmap (and I'm not sure why you are making it the same size as the original bitmap). From the log, you have used 25MB of Java allocations, and 18MB of bitmap allocations, so you are basically right up against the 48MB heap limit.
Also I think it is very unlikely that createScaledBitmap() leaks. All it does is basically what you are doing here.
您应该尝试在 BitmapFactory.Options 类中使用变量“inSampleSized”。这将在不使用多余内存的情况下进行扩展。
http://developer.android.com/reference/android/graphics /BitmapFactory.Options.html#inSampleSize
You should try to use the variable "inSampleSized" in the BitmapFactory.Options class. This will scale without using excess memory.
http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize
我猜你真的已经接近堆限制了。在您的函数中,您基本上正在实例化第二个位图,这大致导致内存加倍(位图非常大)。如果您使用的操作系统早于 Honeycomb,那么查看打印在某处的内存值也会产生误导。 iirc,位图直接保存在系统内存堆上,而其他所有内容都保存在虚拟机堆上(这些是您看到的值 -> 2,5MB)。但是,位图分配的内存也计入内存堆限制。 :/
我建议您看一下 Google I/O 会议:http://www.youtube .com/watch?v=_CruQY55HOk
我认为你的问题只能通过降低位图的分辨率或使用某些缩放函数来解决,这不会实例化新的位图并修改现有的一个(如 AmandeepGrewal 提到的那个)。
I guess you´re really close to the heap limit. In your function, you basically are instantiating a second Bitmap, which roughly leads to doubling your memory (Bitmaps are very large). If you´re on an OS earlier than Honeycomb, it´s also misleading to look at memory values, which are printed out somewhere. iirc, Bitmaps are held directly on the system memory heap, whereas everything other is held on the vm heap (and these are the values you see -> 2,5MB). However, the memory for Bitmap allocations also counts in for the memory heap limit. :/
I suggest you have a look at this Google I/O Session: http://www.youtube.com/watch?v=_CruQY55HOk
I think your problem can only be solved by bringing down the resolution of your Bitmap or by using some scale function, that doesn´t instantiate a new Bitmap and modifies the existing one (like the one mentioned by AmandeepGrewal).