【问题标题】:Scaling images in Android causes OutOfMemory exception在 Android 中缩放图像会导致 OutOfMemory 异常
【发布时间】:2011-09-03 18:26:25
【问题描述】:

我正在开发一个由许多图像作为精灵组成的 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(...),因为这种方法会在内部发生内存泄漏(如其他在线资源中所述)。

提前谢谢你,
兹拉特科

【问题讨论】:

标签: android bitmap out-of-memory image-scaling recycle


【解决方案1】:

您可能非常接近内存限制。看起来您正在创建一个非常大的位图(我不确定为什么要将其设置为与原始位图相同的大小)。从日志中可以看出,您使用了 25MB 的 Java 分配和 18MB 的位图分配,因此您基本上正好达到了 48MB 的堆限制。

我还认为 createScaledBitmap() 泄漏的可能性很小。它所做的基本上就是你在这里所做的。

【讨论】:

  • 为什么第一个代码sn-p从来没有导致OOM异常?事实上,在第二个 sn-p 中,我将原始位图缩放到其大小的 80%。已分配,有 2.5MB 而不是 25MB
【解决方案2】:

您应该尝试在 BitmapFactory.Options 类中使用变量“inSampleSized”。这将在不使用过多内存的情况下进行扩展。

http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize

【讨论】:

  • "inSampleSize" 是一个 int 变量 >=1,因此我无法很好地控制缩放因子。游戏需要特定的放大和缩小因子,例如0.7688
  • 调整大小时是否需要保存位图?绘制位图时,为什么不在要绘制的画布上应用矩阵。较大的位图将在内存中,但这样可能会使用较少的内存,因为不需要分配另一个位图。
【解决方案3】:

我猜你真的接近堆限制了。在您的函数中,您基本上是在实例化第二个位图,这大致导致您的内存加倍(位图非常大)。如果您使用的操作系统早于 Honeycomb,那么查看内存值也会产生误导,这些内存值会打印在某处。 iirc,位图直接保存在系统内存堆上,而其他所有内容都保存在 vm 堆上(这些是您看到的值 -> 2,5MB)。但是,用于位图分配的内存也计入内存堆限制。 :/

我建议你看看这个 Google I/O 会议:http://www.youtube.com/watch?v=_CruQY55HOk

我认为您的问题只能通过降低位图的分辨率或使用一些缩放功能来解决,该功能不会实例化新的位图并修改现有的位图(如 AmandeepGrewal 提到的那个)。

【讨论】:

  • 感谢您的链接。这真的很有教育意义。至于问题,我无法降低分辨率,因为它应该被严格定义。此外,我尝试了缓存所有已加载资源的解决方案。当我不进行图像回收时,我最终会出现 OutOfMemory。当我回收时,我得到 SIGNAL 11 (WIN_DEATH) 本机错误,难以调试。真的很郁闷……
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-27
  • 2014-08-10
  • 1970-01-01
相关资源
最近更新 更多