大位图内存不足异常

outofmemory exception for Large Bitmap

我找到了很多关于如何加载大位图和避免内存不足异常的文档。但问题是我必须从我的 MediaStore.Images.media 中获取图像,所以经典的 google 文档中指出的 decodeFile(path,options) 对我不起作用

正如您在下面看到的,我对行 // Bitmap photo= Mediastore.Images 进行了注释,这是触发内存不足的行。在另一边添加 Bitmap bm=BitmapFactory.decodeFile(selectedImageToUri,options) returns null 行,尽管编译器可以看到 selectedImageToUri 中的路径(表示图片所在的内容提供者)而不是选项值,即我设置为8,因为我想缩小所有图像

我的问题是如何在 bm 中插入引用用户在图库中选择的图像的位图。在行 BitMap photo does not return null 并且工作得很好,但我取消了评论,因为在我更改了几张图片后出现内存不足异常。

@Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable final Bundle savedInstanceState) {


        if (flagVariable) {

            if (selectedImageToUri != null) {


                // BitMap photo = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), Uri.parse(selectedImageToUri));


                final BitmapFactory.Options options= new BitmapFactory.Options();
                options.inSampleSize=8;


                Bitmap bm = BitmapFactory.decodeFile(selectedImageToUri, options);

                pic = new BitmapDrawable(bm);


                getActivity().getWindow().setBackgroundDrawable(pic);


            } else {
                getDefaultImageBackground(inflater, container);

            }


            hiddenList = inflater.inflate(R.layout.fragment_as_list_layout_temp, container, false);

        } else {
            getDefaultImageBackground(inflater, container);
        }

        listView = (ListView) hiddenList.findViewById(R.id.list_hidden);

MediaStore.getBitmap只是一个简单的方便方法,它看起来像这样:

public static final Bitmap getBitmap(ContentResolver cr, Uri url)
                throws FileNotFoundException, IOException {
    InputStream input = cr.openInputStream(url);
    Bitmap bitmap = BitmapFactory.decodeStream(input);
    input.close();
    return bitmap;
}

您可以基于此创建自己的方法,该方法采用 options 并在 BitmapFactory 上调用不同的重载:

public static final Bitmap getBitmap(ContentResolver cr,
                                     Uri url,
                                     BitmapFactory.Options options)
                throws FileNotFoundException, IOException {
    InputStream input = cr.openInputStream(url);
    Bitmap bitmap = BitmapFactory.decodeStream(input, null, options);
    input.close();
    return bitmap;
}

用法:

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;

Bitmap bm = getBitmap(getActivity().getContentResolver(),
                      Uri.parse(selectedImageToUri),
                      options);

我在这个问题上花了很多时间,但没有人给我确切的答案,最后我解决了。首先创建方法并提供图像 URI 作为参数,这将 return 位图基本上在这里我计算图像大小的基础上,我们可以管理内存和图像并以位图形式获取精确图像。

你甚至可以显示 5000×8000 和 12MiB 图片,没有任何错误代码测试只需复制粘贴到你的 class 并享受。

使用

Bitmap mBitmap = getPhoto(MYIMAGEURI);

向方法提供URI并获取位图

Bitmap getPhoto(Uri selectedImage) {
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    int height = metrics.heightPixels;
    int width = metrics.widthPixels;
    Bitmap photoBitmap = null;
    InputStream inputStream = null;
    try {
        inputStream = getContentResolver().openInputStream(selectedImage);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
    bitmapOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(inputStream, null, bitmapOptions);
    int imageWidth = bitmapOptions.outWidth;
    int imageHeight = bitmapOptions.outHeight;

    @SuppressWarnings("unused")
    InputStream is = null;
    try {
        is = getContentResolver().openInputStream(selectedImage);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    float scale = 1.0f;

    if (imageWidth < imageHeight) {
        if (imageHeight > width * 1.0f) {
            scale = width * 1.0f / (imageHeight * 1.0f);
        }

    } else {
        if (imageWidth > width * 1.0f) {
            scale = width * 1.0f / (imageWidth * 1.0f);
        }

    }

    photoBitmap = decodeSampledBitmapFromResource(this,
            selectedImage, (int) (imageWidth * scale),
            (int) (imageHeight * scale));
    return photoBitmap;
}

使用图像大小解码位图样本

public static Bitmap decodeSampledBitmapFromResource(Context context,
            Uri uri, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    InputStream is = null;
    try {
        is = context.getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    BitmapFactory.decodeStream(is, null, options);

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

    // Decode editBitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    InputStream inputs = null;
    try {
        inputs = context.getContentResolver().openInputStream(uri);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    return BitmapFactory.decodeStream(inputs, null, options);
}

计算样本大小

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;

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

        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float) height
                / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = Math.min(heightRatio, widthRatio);
        // inSampleSize = heightRatio < widthRatio ? heightRatio :
        // widthRatio;
    }

    return inSampleSize;
}

或者可以使用 manifiest.xml 中的一行代码解决 在应用程序标签中使用此

android:largeHeap="true"