Sau một vài ngày vật lộn để tránh tất cả các lỗi OutOfMemory mà tôi đã nhận được với các thiết bị khác nhau, tôi tạo này:
private Bitmap getDownsampledBitmap(Context ctx, Uri uri, int targetWidth, int targetHeight) {
Bitmap bitmap = null;
try {
BitmapFactory.Options outDimens = getBitmapDimensions(uri);
int sampleSize = calculateSampleSize(outDimens.outWidth, outDimens.outHeight, targetWidth, targetHeight);
bitmap = downsampleBitmap(uri, sampleSize);
} catch (Exception e) {
//handle the exception(s)
}
return bitmap;
}
private BitmapFactory.Options getBitmapDimensions(Uri uri) throws FileNotFoundException, IOException {
BitmapFactory.Options outDimens = new BitmapFactory.Options();
outDimens.inJustDecodeBounds = true; // the decoder will return null (no bitmap)
InputStream is= getContentResolver().openInputStream(uri);
// if Options requested only the size will be returned
BitmapFactory.decodeStream(is, null, outDimens);
is.close();
return outDimens;
}
private int calculateSampleSize(int width, int height, int targetWidth, int targetHeight) {
int inSampleSize = 1;
if (height > targetHeight || width > targetWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/(float) targetHeight);
final int widthRatio = Math.round((float) width/(float) targetWidth);
// 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 = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
private Bitmap downsampleBitmap(Uri uri, int sampleSize) throws FileNotFoundException, IOException {
Bitmap resizedBitmap;
BitmapFactory.Options outBitmap = new BitmapFactory.Options();
outBitmap.inJustDecodeBounds = false; // the decoder will return a bitmap
outBitmap.inSampleSize = sampleSize;
InputStream is = getContentResolver().openInputStream(uri);
resizedBitmap = BitmapFactory.decodeStream(is, null, outBitmap);
is.close();
return resizedBitmap;
}
Phương pháp này làm việc với tất cả các thiết bị tôi kiểm tra, nhưng tôi nghĩ rằng chất lượng có thể tốt hơn bằng cách sử dụng quá trình khác mà tôi không biết.
Tôi hy vọng mã của mình có thể giúp các nhà phát triển khác trong cùng một tình huống. Tôi cũng đánh giá cao nếu một nhà phát triển cao cấp có thể giúp đỡ, đưa ra một gợi ý về quá trình khác để tránh mất (ít hơn) chất lượng trong quá trình này.
Nguồn
2013-06-15 16:54:00
Trang web chính thức của [Đào tạo Android] (http://developer.android.com/training/index.html) hiện có một lớp được gọi là [Hiển thị bitmap hiệu quả] (http://developer.android.com/training/ display-bitmaps/index.html) với một bài học, [Tải các bitmap lớn một cách hiệu quả] (http://developer.android.com/training/displaying-bitmaps/load-bitmap.html) mà đi qua điều này. Bài học [Caching Bitmaps] (http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html) cũng bao gồm một số thông tin về bộ nhớ đệm bằng bộ nhớ cache tham chiếu cứng thay vì WeakReference hoặc SoftReference. – AdamK