Avoid OOM with BItmap
Source: StackOverflow
Question: How to avoid Out Of Memory error on Android when dealing with bitmap.
Answer: Unless you're absolutely sure the Bitmap
is small then instead of using this generic method to load Bitmap
from resource:
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
Use this one to subsample the image to a smaller one with good enough quality for displaying:
public static final int BITMAP_THRESHOLD = 500; //maximum dimension for subsampled bitmap
public static Bitmap loadSubsampledBitmap(Context ctx, Uri uri, int threshold) throws FileNotFoundException, IOException{
InputStream input = ctx.getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither=true;//optional
onlyBoundsOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
input.close();
if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1))
return null;
Log.d(TAG, "TEST_SUBSAMPLE original width: " + onlyBoundsOptions.outWidth + " height: " + onlyBoundsOptions.outHeight);
int originalSize = (onlyBoundsOptions.outHeight > onlyBoundsOptions.outWidth) ? onlyBoundsOptions.outHeight : onlyBoundsOptions.outWidth;
double ratio = (originalSize > threshold) ? (originalSize / threshold) : 1.0;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = getPowerOfTwoForSampleRatio(ratio);
bitmapOptions.inDither=true;//optional
bitmapOptions.inPreferredConfig=Bitmap.Config.ARGB_8888;//optional
input = ctx.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
input.close();
Log.d(TAG, "TEST_SUBSAMPLE subsampled width: " + bitmap.getWidth() + " height: " + bitmap.getHeight());
return bitmap;
}
private static int getPowerOfTwoForSampleRatio(double ratio){
int k = Integer.highestOneBit((int)Math.floor(ratio));
if(k==0) return 1;
else return k;
}