3

下面的代码会导致 OutOfMemory 吗?我认为它允许超过应用程序内存限制。

Matrix matrix = new Matrix();
matrix.postRotate(orientation);

image = Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), matrix, true);

在 Android 中旋转图像的最佳方法是什么?

在新进程中的服务中分配它以获得更多堆?

@CommonsWare 在此链接 [1] 中表示,许多开发人员认为更多的堆是低效编码的解决方案。

这个问题也表明大堆[2]。

有没有更简单的解决方案?

[1]你能在一个单独的进程上启动一个 IntentService 吗?

[2]旋转图像时如何避免OutOfMemory ex?

4

4 回答 4

2

简短的回答是,是的,此代码可能会导致 OutOfMemory。我认为没有比增加应用程序堆大小更简单的解决方案了。我相信@CommonsWare 是对的,而且 OutOfMemory 通常表明编程错误。但是在某些情况下,您需要,嗯,巨大的内存。旋转巨大的图像绝对是这种情况之一。

您可以使用本机代码 (NDK) 而不是要求增加堆大小,但这绝对不容易。而且它仍然需要大量内存,因此使用 C++ 没有任何优势(除了它适用于 2.3)。

于 2013-08-22T06:03:55.990 回答
1

如果您希望使用基于 NDK 的解决方案,我在这里创建了一个,并且在这里创建了一个 github 项目。

这将通过将数据放入本机 C“世界”、回收旧数据并在轮换后返回结果来避免 OOM。

它不需要任何下采样。

于 2014-01-26T16:00:40.323 回答
0

当您的位图太大而无法加载到内存中时,抛出 OutOfMemoryException。

在这里,我给你一个解决方案。

BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap=BitmapFactory.decodeStream(is,null,options);

使用 BitmapFactory.Options 类的 inSampleSize 属性。

如果设置为大于 1 的值,则请求解码器对原始图像进行二次采样,返回较小的图像以节省内存。样本大小是对应于解码位图中的单个像素的任一维度中的像素数。例如, inSampleSize == 4 返回的图像是原始宽度/高度的 1/4,像素数的 1/16。任何 <= 1 的值都被视为 1。注意:解码器使用基于 2 的幂的最终值,任何其他值将向下舍入到最接近的 2 幂。

//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
    //Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f),null,o);

    //The new size we want to scale to
    final int REQUIRED_SIZE=70;

    //Find the correct scale value. It should be the power of 2.
    int scale=1;
    while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
        scale*=2;

    //Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize=scale;
    return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
于 2013-08-22T06:34:05.547 回答
0

这里:

image = Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), matrix, true);

代码操作两个位图,第一个imageBitmap您预先加载/解码到 RAM 中以使用的 - 实际旋转。无论您将结果存储到同一个变量中,第二个都将由 Bitmap.createBitmap() 创建。无论如何,在这一行,您需要位图 x2 RAM,这肯定会导致 OOM(说到设备的相机最大可能的照片)。
我认为使用 NDK 是这里最好的解决方案。
在此处查看我的相同问题以获取其他可能的解决方案(MappedByteBuffer),它也具有指向 NDK/JNI 解决方案的链接。

于 2015-01-28T12:37:31.237 回答