【问题标题】:getting OutOfMemoryError on image load from file从文件加载图像时出现 OutOfMemoryError
【发布时间】:2014-12-10 19:29:10
【问题描述】:

我知道这个question,据我所知,我实际上正在做与最佳答案建议相同的事情。但是我仍然在内存较少的设备上遇到 outOfMemory 崩溃。

编辑:我只是用手机的原生相机拍照。没什么好看的。

private Bitmap setImgViewFromFile(ImageView imgView, String file) {
    // Get the dimensions of the View
    int targetW = Math.max(imgView.getWidth(), 600);
    int targetH = Math.max(imgView.getHeight(), 800);


    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(file, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW / targetW, photoH / targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(file, bmOptions);
    imgView.setImageBitmap(bitmap);
    return bitmap;
}

堆栈跟踪:

12-10 10:38:04.120    4144-4144/com.loop E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.loop, PID: 4144
java.lang.OutOfMemoryError
        at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
        at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:613)
        at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:589)
        at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:369)

谁能看出我做错了什么?

【问题讨论】:

  • 请记住,不能保证任何特定的样本大小都会起作用,因为不能保证有足够大的空闲内存块用于任何给定的位图。
  • 你的比例计算不对。但是由于您现在将缩小太多,因此不会导致内存不足错误。内存小的设备的屏幕是否大于 800x600?
  • 只有 2 的幂才能保证为比例因子。那个相机的分辨率是多少。还有你内存不足的相机?

标签: android


【解决方案1】:

改变:

// Determine how much to scale down the image
int scaleFactor = Math.min(photoW / targetW, photoH / targetH);

// Determine how much to scale down the image
int scaleFactor = findBestSampleSize(photoW , photoH ,targetW,targetH);

findBestSampleSize 是:

/**
 * Returns the largest power-of-two divisor for use in downscaling a bitmap
 * that will not result in the scaling past the desired dimensions.
 *
 * @param actualWidth Actual width of the bitmap
 * @param actualHeight Actual height of the bitmap
 * @param desiredWidth Desired width of the bitmap
 * @param desiredHeight Desired height of the bitmap
 */
// Visible for testing.
static int findBestSampleSize(
        int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) {
    double wr = (double) actualWidth / desiredWidth;
    double hr = (double) actualHeight / desiredHeight;
    double ratio = Math.min(wr, hr);
    float n = 1.0f;
    while ((n * 2) <= ratio) {
        n *= 2;
    }

    return (int) n;
}

如果仍然得到OOM,请将float n = 1.0f; 更改为float n = 2.0f;float n = 4.0f; 或...

【讨论】:

  • 谢谢@mmlooloo,你能解释一下while循环在做什么吗?根据文档,“解码器使用基于 2 的幂的最终值,任何其他值将向下舍入到最接近的 2 幂。”
  • 它找到小于或等于比率的最接近的 2 幂。它从 1 开始乘以 2 直到小于或等于比率。换句话说,“基于 2 的幂的最终值,任何其他值都将向下舍入到最接近的 2 幂”
  • 但是如果api已经这样做了,为什么还需要手动完成呢?是为了效率吗?
  • 抱歉一直在窃听,我想你错过了理解我的问题。文档说“基于 2 的幂的最终值,任何其他值都将向下舍入到最接近的 2 次幂”,这是否意味着系统会将其向下舍入到最接近的 2 次幂?还是他们的意思是说“您(开发人员)必须将其四舍五入到 2 的幂”?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
  • 2017-09-20
  • 2015-07-29
  • 2012-03-21
  • 2013-01-29
相关资源
最近更新 更多