exception – OutofMemoryError: bitmap size exceeds VM budget (Android)-ThrowExceptions

Exception or error:

Getting an Exception in the BitmapFactory. Not sure what is the issue. (Well I can guess the issue, but not sure why its happening)

ERROR/AndroidRuntime(7906): java.lang.OutOfMemoryError: bitmap size exceeds VM budget

ERROR/AndroidRuntime(7906):     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:295)

My code is pretty straight forward. I defined an XML layout w/ a default image. I try to load a bm on the SDCard (if present – it is). If not it shows the default image. Anyway.. Here is code :

public class showpicture extends Activity {
  public void onCreate(Bundle savedInstanceState) {

         /** Remove menu/status bar **/
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         final Window win = getWindow();   
         win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

            Bitmap bm;
         super.onCreate(savedInstanceState);
         setContentView(R.layout.showpicture);
            try {
         ImageView mImageButton = (ImageView)findViewById(R.id.displayPicture);
         bm = Bitmap.createScaledBitmap(BitmapFactory.decodeFile("/sdcard/dcim/Camera/20091018203339743.jpg"),100, 100, true);
         parkImageButton.setImageBitmap(bm);
         }
         catch (IllegalArgumentException ex) {
          Log.d("MYAPP",ex.getMessage());
         } 
            catch (IllegalStateException ex) {

It fails on the bm=Bitmap.createScaledBitmap any thoughts? I did some research on the forums, and it pointed to this post
I just don’t know why it is not working. Any help would be great! Thanks,

Chris.

How to solve:

http://code.google.com/p/android/issues/detail?id=8488

http://mobi-solutions.blogspot.com/2010/08/how-to-if-you-want-to-create-and.html

###

inSampleSize is a good hint. But a fixed value often doesn’t work fine, since large bitmaps from files usually are user files, which can vary from tiny thumbnails to 12MP images from the digicam.

Here’s a quick and dirty loading routine. I know there’s room for improvement, like a nicer coded loop, using powers of 2 for faster decoding, and so on. But it’s a working start…

public static Bitmap loadResizedBitmap( String filename, int width, int height, boolean exact ) {
    Bitmap bitmap = null;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile( filename, options );
    if ( options.outHeight > 0 && options.outWidth > 0 ) {
        options.inJustDecodeBounds = false;
        options.inSampleSize = 2;
        while (    options.outWidth  / options.inSampleSize > width
                && options.outHeight / options.inSampleSize > height ) {
            options.inSampleSize++;
        }
        options.inSampleSize--;

        bitmap = BitmapFactory.decodeFile( filename, options );
        if ( bitmap != null && exact ) {
            bitmap = Bitmap.createScaledBitmap( bitmap, width, height, false );
        }
    }
    return bitmap;
}

Btw, in the newer APIs there are also lots of BitmapFactory.Option’s for fitting the image to screen DPIs, but I’m not sure whether they really simplify anything. Using android.util.DisplayMetrics.density or simply a fixed size for less memory consumption seem to work better imho.

###

With reference to this link, please note the outOfMemory error can be solved by the following way:

public Bitmap decodeFile(String filePath) {

Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inPurgeable = true;

try {
BitmapFactory.Options.class.getField("inNativeAlloc").setBoolean(options,true);

} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (SecurityException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (NoSuchFieldException e) {
    e.printStackTrace();
}

if(filePath != null)
{
    bitmap = BitmapFactory.decodeFile(filePath, options);               
}

return bitmap;
}

###

Make sure to guard your bitmap creation from out of memory errors! With most platforms, android doesn’t have much memory to play with and it runs out quickly with bitmaps. Also, make sure to manually recycle your bitmaps as much as possible, I’ve noticed that the garbage collection can be rather slow.

try{            
  Bitmap myFragileBitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
}
catch(IllegalArgumentException e){
  Log.e(TAG,"Illegal argument exception.");
}
catch(OutOfMemoryError e){
  Log.e(TAG,"Out of memory error :(");
}

###

I ended up resizing the bitmap using the following code which seems to have resolved the issue.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeFile(mPathName, options);

###

I think it is – what it it say it is. Your image is too big and since it is loaded in the stream when the memory is exhausted the exception is thrown. It’s not even the question on how much memory you have overall but how much your particular Activity has available.

###

use these options in decodefile. hope u can elemenate bitmap exceeds vm budget problem..

BitmapFactory.Options bfOptions=new BitmapFactory.Options(); 

bfOptions.inDither=false;          //Disable Dithering mode
bfOptions.inPurgeable=true;       //Tell to gc that whether it needs free memory, the Bitmap can be cleared
bfOptions.inInputShareable=true;  //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
bfOptions.inTempStorage=new byte[32 * 1024]; 

###

Have you checked the DDMS?
With what I have been encountering, it’s probably not the size of the images, because Android seems to handle large images pretty well.
If you trace the heap with DDMS you may find that you happen to have a lot of free memory.
You can “expand” your heap by adding this

static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }    

to your code, to force the heap to expand. It may make it a bit less frequent.
Unfortunately, with the exception it claims that it can’t allocate some amount of bytes. Say 1M. If you take a look at the “free” line you will see that the largest block is >> 1M.
There is something strange there that I can’t figure out. It is not related even to the speed of swiping images.
I saw in some thread that you can call “recycle” or so for bitmaps. I still don’t see why it should help if the heap size is way above the taken size.

###

I got this error when i began to resize an image from 320×240 to something like 64×240 (downscale), then import into my project (since i wanted to improve rendering speed and it contained a lot of useless alpha regions until this point).

now the last answer makes much sense:

You can “expand” your heap by adding this static { @SuppressWarnings(“unused”) byte dummy[] = new byte[ 8*1024*1024 ]; }
to your code, to force the heap to expand. It may make it a bit less
frequent.

I think this is what happened to me. Android automatically decodes drawables into bitmaps, (and then get stored on a heap, all on compilation time?)

i began seeing the error, when i used the smaller version of my image in runtime (i scale them up on runtime since i program a VGA-game with retro graphics, using BitmapFactory.decodeResource and Bitmap.createScaledBitmap).

it must be like Marve said: The Heap is not big enough in my case after shrinking my drawable/image and import it into my project.

I was able to get rid of my OutOfMemoryException when resizing the image back to a bigger size (320×240), which verifies the problem i guess?

Leave a Reply

Your email address will not be published. Required fields are marked *