从Uri

时间:2016-04-27 09:18:41

标签: android bitmap

我使用以下方法从Bitmap

获取Uri
private static Bitmap getBitmapFromUri(@NonNull Context context, @NonNull Uri uri) throws IOException {

        ParcelFileDescriptor parcelFileDescriptor =
                context.getContentResolver().openFileDescriptor(uri, "r");
        assert parcelFileDescriptor != null;
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
    }

问题是,我有时会在Crashlytics的return语句中收到OOM错误。我认为它正在发生,因为所选图像的尺寸很大。如何修改它以便返回Bitmap的最佳质量缩小版本,以便它不会导致内存不足错误?

编辑我自己发布了一个答案。请看一下,让我知道这是正确的方法。

5 个答案:

答案 0 :(得分:2)

您必须在解码前调整图像大小。这是我的代码,用于解码图像并在图像视图中显示它。

private void loadImage(Uri u, String path) {
    try {
        ContentResolver cr = context.getContentResolver();
        InputStream in;
        in = cr.openInputStream(u);
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(in, null, o);
        in.close();

        int scale = 1;
        if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
            scale = (int) Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        in = cr.openInputStream(u);
        Bitmap bitmap = BitmapFactory.decodeStream(in, null, o2);
        in.close();
        Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), getRotation(path), true);

        int nh = (int) ( rotatedBitmap.getHeight() * (512.0 / rotatedBitmap.getWidth()) );
        Bitmap scaled = Bitmap.createScaledBitmap(rotatedBitmap, 512, nh, true);
        String pathTest = MediaStore.Images.Media.insertImage(context.getContentResolver(), scaled, "Title", null);
        ImageLoader imageLoader = ImageLoader.getInstance();
        imageLoader.displayImage(Uri.decode(Uri.parse(pathTest).toString()), mPicture, new ImageLoadingListener() {
            @Override
            public void onLoadingStarted(String imageUri, View view) {

            }

            @Override
            public void onLoadingFailed(String imageUri, View view, FailReason failReason) {

            }

            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                mPicture.setImageBitmap(loadedImage);
            }

            @Override
            public void onLoadingCancelled(String imageUri, View view) {

            }
        });
    } catch (Exception e) {
        //Toast.makeText(context, context.getString(R.string.fail_to_load_image), Toast.LENGTH_SHORT).show();
        Log.e("TAG", e.toString());
    }
}

private Matrix getRotation(String pathPetPicture) {
    Matrix matrix = new Matrix();
    try {
        ExifInterface exif = new ExifInterface(pathPetPicture);
        int rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);

        switch (rotation) {
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                matrix.setScale(-1, 1);
                break;

            case ExifInterface.ORIENTATION_ROTATE_180:
                matrix.setRotate(180);
                break;

            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                matrix.setRotate(180);
                matrix.postScale(-1, 1);
                break;

            case ExifInterface.ORIENTATION_TRANSPOSE:
                matrix.setRotate(90);
                matrix.postScale(-1, 1);
                break;

            case ExifInterface.ORIENTATION_ROTATE_90:
                matrix.setRotate(90);
                break;

            case ExifInterface.ORIENTATION_TRANSVERSE:
                matrix.setRotate(-90);
                matrix.postScale(-1, 1);
                break;

            case ExifInterface.ORIENTATION_ROTATE_270:
                matrix.setRotate(-90);
                break;

            case ExifInterface.ORIENTATION_NORMAL:
            default:
                break;
        }
    } catch (Exception e) {
        Log.e("TAG", e.toString());
    }

    return matrix;
}

答案 1 :(得分:2)

尝试这样的事情......

{{1}}

愿它有所帮助。

如果您想要有效地加载大位图,请关注RenderableSeriesSourceCollection

答案 2 :(得分:1)

Bitmap bm;
bm = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(filepath), 100, 100,     true);
mPicture = new ImageView(context);
mPicture.setImageBitmap(bm);

使用此选项并在getBitmapFromUri()

中将代码替换为此代码

答案 3 :(得分:1)

我读了所有的答案,这就是我打算做的,告诉我它是否有用。在我的Application课程中,在onCreate()中,我将设备的宽度和高度(以像素为单位)存储在SharedPreferences中。在修改后的代码中,我根据设备像素缩放位图。希望它能免除OOM错误。

private static Bitmap getBitmapFromUri(@NonNull Context context, @NonNull Uri uri) throws IOException {

        ParcelFileDescriptor parcelFileDescriptor =
                context.getContentResolver().openFileDescriptor(uri, "r");
        assert parcelFileDescriptor != null;
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();

        TinyDB tinyDB = new TinyDB(context);
        int maxSize = Math.min(tinyDB.getInt(AppConstants.DEVICE_WIDTH, 720), tinyDB.getInt(AppConstants.DEVICE_HEIGHT, 1080));
        int outWidth;
        int outHeight;
        int inWidth = image.getWidth();
        int inHeight = image.getHeight();
        if(inWidth > inHeight){
            outWidth = maxSize;
            outHeight = (inHeight * maxSize) / inWidth;
        } else {
            outHeight = maxSize;
            outWidth = (inWidth * maxSize) / inHeight;
        }

        return Bitmap.createScaledBitmap(image, outWidth, outHeight, false);
    }

答案 4 :(得分:0)

使用GlidePicasso库:

将路径替换为本地文件夹路径或服务器URL

Glide.with (context).load (path).asBitmap().into(imageView);