【问题标题】:MediaStore.Images.Media.getBitmap and out of memory errorMediaStore.Images.Media.getBitmap 和内存不足错误
【发布时间】:2012-07-08 00:41:24
【问题描述】:

我的代码是:

public Bitmap loadPhoto(Uri uri) {
    Bitmap scaled = null;
    try {
    scalled = Bitmap.createBitmap(
      MediaStore.Images.Media.getBitmap(getContentResolver(), uri),
      0,0,90, 90);

    if (scaled == null) { return null; }
    } catch(Exception e) { }
    return scaled;
}

在这之后。我在 ImageView 中显示缩放。每张图片都来自设备摄像头。

每次显示相机中的三张照片后,我都会收到错误:内存不足。如何解决?

【问题讨论】:

标签: android bitmap imageview out-of-memory


【解决方案1】:

Praveen Katha 的答案将始终返回 null。这是更新后的答案。

这里有个窍门,每次使用后关闭输入流。输入流意味着使用一次。更多信息请关注answer

private 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;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) >= reqHeight
                    && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    public static Bitmap decodeSampledBitmapFromUri(Context context, Uri imageUri, int reqWidth, int reqHeight) throws FileNotFoundException {
        Bitmap bitmap = null;
        try {
            // Get input stream of the image
            final BitmapFactory.Options options = new BitmapFactory.Options();
            InputStream iStream = context.getContentResolver().openInputStream(imageUri);

            // First decode with inJustDecodeBounds=true to check dimensions
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(iStream, null, options);
            if (iStream != null) {
                iStream.close();
            }
            iStream = context.getContentResolver().openInputStream(imageUri);

            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeStream(iStream, null, options);
            if (iStream != null) {
                iStream.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

【讨论】:

    【解决方案2】:

    对于那些正在寻找代码示例的人:

    private 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;
    
        if (height > reqHeight || width > reqWidth) {
    
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
    
            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) >= reqHeight
                    && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }
    
        return inSampleSize;
    }
    
    public static Bitmap decodeSampledBitmapFromUri(Context context, Uri imageUri, int reqWidth, int reqHeight) throws FileNotFoundException {
    
        // Get input stream of the image
        final BitmapFactory.Options options = new BitmapFactory.Options();
        InputStream iStream = context.getContentResolver().openInputStream(imageUri);
    
        // First decode with inJustDecodeBounds=true to check dimensions
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(iStream, null, options);
    
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeStream(iStream, null, options);
    }
    

    【讨论】:

    • 你真的亲自尝试过这个功能吗?我试过了,函数 decodeSampledBitmapFromUri 总是返回 null。经过长时间的研究,我发现您不能多次使用相同的输入流作为 BitmapFactory.decodeStream 的参数。
    • 刚刚达到同样的认识。在第一次调用之后,输入流指向文件的末尾。可能有一种方法可以重置它而不是创建一个新的...
    【解决方案3】:

    MediaStore.getBitmap 方法是一种方便的方法,在获取位图时不指定样本大小。如果您正在使用 getBitmap(ContentResolver, Uri),并且想要使用样本大小,只需使用 ContentResolver 获取输入流,然后像往常一样解码位图(先计算样本大小,然后使用适当的加载样本量)。

    【讨论】:

    • 听起来是个好方法,它的代码会更好地回答
    • @weston Google 在link 提供了这个示例代码(关于有效加载位图)。可以通过查看 MediaStore.getBitmap 的实现来找到 ContentResolver 的使用。它以相同的方式调用内容解析器
    • 我知道您可以在其他地方找到答案,因为我必须这样做,因为答案不完整。阅读此答案的每个人都必须做同样的腿部工作。一个好的 Stack Overflow 答案不依赖于外部链接来完成它。
    【解决方案4】:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-20
      • 1970-01-01
      • 2020-10-15
      • 2014-10-21
      • 2016-10-20
      • 2013-01-17
      相关资源
      最近更新 更多