Android中的位图内存不足错误...

6

我正在开发一个Android应用程序,使用位图将图像绑定到ImageView上。我的要求是旋转ImageView并给它加上边框。我已经成功实现了这个功能,但是当应用程序使用此活动两三次后,会出现“强制关闭”错误,显示位图超出VM内存。请帮助我在代码中减少位图内存消耗,并让我知道如何修改代码以实现相同的功能?

final int BORDER_WIDTH = 5;
        // Set the border color
        final int BORDER_COLOR = Color.WHITE;
        Bitmap res = Bitmap.createBitmap(CAPTURE_IMAGE.getWidth() + 2
                * BORDER_WIDTH, CAPTURE_IMAGE.getHeight() + 2 * BORDER_WIDTH,
                CAPTURE_IMAGE.getConfig());
        System.gc();
        Canvas canvas = new Canvas(res);
        Paint paint = new Paint();
        paint.setColor(BORDER_COLOR);
        canvas.drawRect(0, 0, res.getWidth(), res.getHeight(), paint);

        canvas.drawBitmap(CAPTURE_IMAGE, BORDER_WIDTH, BORDER_WIDTH, paint);
        Matrix mat = new Matrix();
        // Set the Imageview position
        mat.postRotate(355);

        bMapRotate = Bitmap.createBitmap(res, 0, 0, res.getWidth(),
                res.getHeight(), mat, true);
        System.gc();
        res.recycle();
        res = null;
        paint = null;
        canvas = null;
        mat = null;
        // Set the captured bitmap image in the imageview
        mShareImageView.setImageBitmap(bMapRotate);

1
我创建了一个不会因为移除最大堆大小限制而避免内存溢出的不错JNI解决方案。这里是链接到我的片段。一些注意事项: - 在代码中用"uint32_t"替换每个"uint16_t"实例(这是我询问的代码错误)。 - 输入和输出位图必须使用8888配置(即ARGB) - 在过程中输入位图将被回收。 - 该代码将图像逆时针旋转90度。当然,您可以根据需要进行更改。 - android developer
4个回答

3

我认为你应该像这样使用收缩函数

bMapRotate = Bitmap.createBitmap(res, 0, 0, res.getWidth(),
                res.getHeight(), mat, true);


Bitmap myBitmap = ShrinkBitmap(bMapRotate , 300, 300);

mShareImageView.setImageBitmap(myBitmap );


private Bitmap ShrinkBitmap(String file, int width, int height) {
        // TODO Auto-generated method stub
        BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
        bmpFactoryOptions.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);

        int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
        int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);

        if (heightRatio > 1 || widthRatio > 1)
        {
         if (heightRatio > widthRatio)
         {
          bmpFactoryOptions.inSampleSize = heightRatio;
         } else {
          bmpFactoryOptions.inSampleSize = widthRatio;
         }
        }

        bmpFactoryOptions.inJustDecodeBounds = false;
        bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);
     return bitmap;
    }

这对我很有帮助,我避免了 VM 内存溢出的 Bitmap 异常。


1
嗨。谢谢回复。但在 ShrinkBitmap 方法中,它传递了一个我没有的参数文件(File)。 - Arun PS
1
但是你必须从某个地方选择文件,不能直接使用它。 - Avi Kumar
2
bMapRotate不是文件路径,而是位图对象。请检查您的代码。 - Arun PS
1
嗯,但我想给你一个想法,你不能获取你的图像路径吗? - Avi Kumar
1
不是的,它存储在位图中。它没有本地文件路径。这就是我问你的原因。 - Arun PS

3
在清单文件中添加 ---> android:largeHeap:"true"

只是提醒其他人:我尝试将这个放在我的清单中的<activity>标签中,它导致了错误,但是当我将它放入<application>标签中时,它就可以工作了。另外,应该是android:largeHeap =“true”。只使用一个冒号。 - Azurespot

1

尝试将gc()调用移动到最后。在设置res = null之后运行,以便它可以释放未使用的内存:

    res.recycle();
    res = null;
    paint = null;
    canvas = null;
    mat = null;
    System.gc();

0
只需在您的清单文件中添加android:largeHeap="true"即可。
参考:largeHeap=true清单标签无法工作?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接