我使用以下方法从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的最佳质量缩小版本,以便它不会导致内存不足错误?
编辑我自己发布了一个答案。请看一下,让我知道这是正确的方法。
答案 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)
答案 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)