如何绕过Android Bitmap内存异常?

时间:2014-03-23 16:05:47

标签: android bitmap

我想将图像显示为屏幕背景,因为我在xml中遇到图像视图scale_type的困难,我正在使用函数中的图像比率和屏幕尺寸进行计算没什么太复杂的

public static Bitmap BitmapToView(Bitmap img, View v) {
    int imgWidth = img.getWidth();
    int imgHeight = img.getHeight();
    int bckWidth = v.getWidth();
    int bckHeight = v.getHeight();
    float ratio1 = (float) bckWidth / imgWidth;
    float ratio2 = (float) bckHeight / imgHeight;
    float maxRatio = Math.max(ratio1, ratio2);
    int newHeight = Math.max((int) (imgHeight * maxRatio), bckHeight);
    int newWidth = Math.max((int) Math.ceil(imgWidth * maxRatio), bckWidth);
    Bitmap tmp_image = Bitmap.createScaledBitmap(img, newWidth, newHeight, true);
    Bitmap ret_image = Bitmap.createBitmap(tmp_image, Math.abs(newWidth - bckWidth)/2, Math.abs(newHeight - bckHeight)/2, bckWidth, bckHeight);
    tmp_image.recycle();
    return ret_image;
}

Options options = new Options();
options.inJustDecodeBounds = false;
Bitmap img = BitmapFactory.decodeFile(imgFilePath, options);
Bitmap newImage = BitmapToView(img, findViewById(R.id.myRelativeLayout);
// RelariveLayout takes up the whole screen ; failing on Samsung Galaxy S4
findViewById(R.id.myRelativeLayout).setBackground(new BitmapDrawable(newimage));

有时我会遇到内存不足的异常 我试图在这里和那里使用.recycle()然后我得到" Canvas:尝试使用回收的位图"

有什么想法吗?感谢

1 个答案:

答案 0 :(得分:1)

你说你已经试过recycle()了?但是我看到你对缩放和未缩放的图像使用相同的变量,你试过这个:

Bitmap image = BitmapFactory.decodeFile("/.../path", options);
...
Bitmap scaledImage = Bitmap.createScaledBitmap(image, newWidth, newHeight, true);
image.recycle(); // <-- Use a new variable for the scaled image so you can recycle the not scaled one

如果这对您没有帮助,请发布更多代码并向我们提供有关您尝试执行的操作的更多信息。否则很难帮助你。

修改

此代码应在缩放之前裁剪小图像,因此应显着减少使用的内存量。

不幸的是我现在无法测试它,但我很确定它应该按预期工作。如果有任何问题随时问。

public static Bitmap BitmapToView(Bitmap img, View v) {
    double imgWidth = img.getWidth();
    double imgHeight = img.getHeight();
    double viewWidth = v.getWidth();
    double viewHeight = v.getHeight();

    // Crop image to required aspect ratio

    double imgRatio = imgWidth / imgHeight;
    double viewRatio = viewWidth / viewHeight;

    double cropWidth;
    double cropHeight;
    if (imgRatio > viewRatio) {
        cropWidth = viewRatio * imgHeight;
        cropHeight = imgHeight;
    } else {
        cropHeight = imgWidth / viewRatio;
        cropWidth = imgWidth;
    }

    int cropX = (int) (imgWidth / 2.0 - cropWidth / 2.0);
    int cropY = (int) (imgHeight / 2.0 - cropHeight / 2.0);

    Bitmap croppedBitmap = Bitmap.createBitmap(img, cropX, cropY, (int)cropWidth, (int)cropHeight);
    img.recycle();

    // Scale image to fill view

    Bitmap finalBitmap = Bitmap.createScaledBitmap(croppedBitmap, (int)viewWidth, (int)viewHeight, true);
    croppedBitmap.recycle();
    return finalBitmap;
}