带位图的Android内存不足异常

时间:2013-02-22 18:09:31

标签: android memory memory-management bitmap out-of-memory

首先,我阅读了许多关于内存不足异常的帖子和文章,但没有一个对我的情况有所帮助。我要做的是从SD卡加载图像,但将其缩放到精确的像素大小。

我首先得到图像的宽度和高度并计算样本大小:

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(backgroundPath, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, getWidth(), getHeight());

以下是我获取样本量的方法(尽管它并不相关):

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {

    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    // NOTE: we could use Math.floor here for potential better image quality
    // however, this also results in more out of memory issues
    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }

    return inSampleSize;
}

现在我有一个样本大小,我将图像从磁盘加载到一个近似大小(样本大小):

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    options.inPurgeable = true;
    Bitmap bmp = BitmapFactory.decodeFile(backgroundPath, options);

现在,我将我创建的这个位图缩放到我需要的确切大小并清理:

    // scale the bitmap to the exact size we need
    Bitmap editedBmp = Bitmap.createScaledBitmap(bmp, (int) (width * scaleFactor), (int) (height * scaleFactor), true); 

    // clean up first bitmap
    bmp.recycle();
    bmp = null;
    System.gc();    // I know you shouldnt do this, but I'm desperate 

以上步骤通常会让我的内存异常异常。有没有人知道从磁盘加载精确大小的位图的方法,以避免像上面那样创建两个单独的位图?

此外,当用户第二次运行此代码(设置新图像)时,似乎会出现更多异常。但是,我确保卸载从位图创建的drawable,它允许在再次运行此代码之前对其进行垃圾回收。

有什么建议吗?

谢谢, 尼克

2 个答案:

答案 0 :(得分:2)

在您的情况下,执行第一次解码后无需创建中间位图。由于您正在绘制到Canvas,您可以使用以下方法(无论哪种方法最方便)将图像缩放到完美尺寸。

drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)

drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)

答案 1 :(得分:0)

也许这种方法会有所帮助,我想我自己将它从stackoverflow中删除了。它解决了我的内存异常问题。

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=250;

        //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;
}