Catching OutOfMemoryError in decoding Bitmap

I did something like this: I catch the error only for try to scale down the image until it works. Eventually it can not work at all; then returns null; otherwise, in success, returns the bitmap.

Outside I decide what to do with the bitmap whether it's null or not.

// Let w and h the width and height of the ImageView where we will place the Bitmap. Then:

// Get the dimensions of the original bitmap
BitmapFactory.Options bmOptions= new BitmapFactory.Options();
bmOptions.inJustDecodeBounds= true;
BitmapFactory.decodeFile(path, bmOptions);
int photoW= bmOptions.outWidth;
int photoH= bmOptions.outHeight;

// Determine how much to scale down the image. 
int scaleFactor= (int) Math.max(1.0, Math.min((double) photoW / (double)w, (double)photoH / (double)h));    //1, 2, 3, 4, 5, 6, ...
scaleFactor= (int) Math.pow(2.0, Math.floor(Math.log((double) scaleFactor) / Math.log(2.0)));               //1, 2, 4, 8, ...

// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds= false;
bmOptions.inSampleSize= scaleFactor;
bmOptions.inPurgeable= true;

do
{
    try
    {
        Log.d("tag", "scaleFactor: " + scaleFactor);
        scaleFactor*= 2;
        bitmap= BitmapFactory.decodeFile(path, bmOptions);
    }
    catch(OutOfMemoryError e)
    {
        bmOptions.inSampleSize= scaleFactor;
        Log.d("tag", "OutOfMemoryError: " + e.toString());
    }
}
while(bitmap == null && scaleFactor <= 256);

if(bitmap == null)
    return null;

For example, with an image of 3264x2448, the loop iterates 2 times on my phone, and then it works.


It's good practice to catch it once and give decodeFile another chance. Catch it and call System.gc() and try decoding again. There is a high probability that it will work after calling System.gc().

try {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4;
    bitmap = BitmapFactory.decodeFile(file, options);
 } catch (OutOfMemoryError e) {
    e.printStackTrace();

    System.gc();

    try {
        bitmap = BitmapFactory.decodeFile(file);
    } catch (OutOfMemoryError e2) {
      e2.printStackTrace();
      // handle gracefully.
    }
}