大位图的outofmemory异常

时间:2016-04-28 10:35:31

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

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

如下所示,我取消了行// Bitmap photo= Mediastore.Images,即触发内存不足的行Bitmap bm=BitmapFactory.decodeFile(selectedImageToUri,options)。在另一边补充 行null返回selectedImageToUri,虽然编译器可以看到BitMap photo中的路径(表示图片所在的内容提供者)而不是选项值,我设置为8,因为我想要缩放所有图像

我的问题是如何在bm中插入引用用户在库中选择的图像的位图。行@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); 中的行不会返回null并且工作得非常好,但是我已经取消注释,因为在我更改了几个图像之后会给我一些内存异常。

SELECT 
    [Measures].[Store sales]
  * 
    {
      [Occupation].[Occupation].MEMBERS * {[Essai].[All]}
     ,
      {[Occupation].[All]} * [Essai].[Essai].MEMBERS
    } ON COLUMNS
 ,{[Product].[Product Family].MEMBERS} ON ROWS
FROM test;

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

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

使用

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"