I am getting the following error after creating bitmap second time around:

04-17 18:28:09.310: ERROR/AndroidRuntime(3458): java.lang.OutOfMemoryError: bitmap size exceeds VM budget

this._profileBitmap = Bitmap.createBitmap(_profileBitmap, xCoor,  yCoor, width, height);

From log:

04-17 18:27:57.500: INFO/CameraCropView(3458): Original Photo Size: W 1536 x H 2048   
04-17 18:28:06.170: INFO/CameraCropView(3458): xCoor: 291   
04-17 18:28:06.170: INFO/CameraCropView(3458): yCoor: 430    
04-17 18:28:06.170: INFO/CameraCropView(3458): Width: 952  
04-17 18:28:06.170: INFO/CameraCropView(3458): Height: 952  

Since the image is huge I get the error. But the interesting thing is the error does not happen the first time, only when I take the picture the second time, which makes me believe this profileBitmap is NOT destroyed. How do I clean this up?

Solution 1

I had the same problem and fix it this way:

My app was ~18MB size, and when I see how much memory left free I was shocked - 654KB (on 1GB RAM!). So I just deleted almost all images from project and downloaded them from the internet on first start, and use pics from SD card when needed.

To check total/free memory for your app use:

 Runtime.getRuntime().totalMemory();
 Runtime.getRuntime().freeMemory();

EDIT: I forgot the main thing - add in your manifest, between application tag, this line:

android:largeHeap="true"

Solution 2

There are many problems with memory exceptions with bitmaps on Android, many of which are discussed on stackoverflow. It would probably be best if you went through the existing questions to see if yours matches one of the existing ones, then if not, write up what makes your situation different.

Some examples:

Out of memory exception due to large bitmap size

Android: out of memory exception in Gallery

Android handling out of memory exception on image processing

etc: https://stackoverflow.com/search?q=android+out+of+memory+exception+bitmap

Solution 3

android bitmap processing tips

Now here are tips which you can follow and can avoid out of memory exception in your Android Application.

  1. Always use Activity context instead of Application context. because Application context cannot be garbage collected. And release resources as your activity finishes. (life cycle of object should be same as of activity).

2 . When Activity finishes. Check HEAP DUMP (memory analysis tool in Android studio).

If there are objects in HEAP DUMP from finished activity there is memory leak. review your code and identify what is causing memory leak.

  1. Always use inSampleSize

Now what is inSampleSize ? with the help of inSampleSize you are actually telling the decoder not to grab every pixel in memory, instead sub sample image. This will cause less number of pixels to be loaded in memory than the original image. you can tell decoder to grab every 4th pixel or every second pixel from original image. if inSampleSize is 4. decoder will return an Image that is 1/16 the number of pixels in original image.

so how much memory you have saved ? calculate :)

  1. Read Bitmap Dimensions before loading into memory.

    How reading bitmap dimensions before loading image into memory can help you avoid out of
    memory error ? Let's Learn

    use inJustBounds = true

here is technique with the help of which you can get image dimension beore loading it in memory

 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inJustDecodeBounds = true;
 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.id.myimage,    options);
 int imageHeight = options.outHeight;
 int imageWidth = options.outWidth;
 String imageType = options.outMimeType;

Above code snippet will not give us any image/bitmap. it will return null for bitmap Object. but it will definitely return width and height of that image. which is R.id.myimage.

Now you have width and height of Image. you can scale up or scale down image based on these factors:

  • ImageView size which will be used to display Image.
  • Available amount of memory. you can check available amount of memory using ActivityManager and getMemoryClass.
  • Screen size and density of device.

    1. Use appropriate Bitmap Configuration

    Bitmap configurations is color space/color depth of an Image. Default bitmap Configuration in Android is RGB_8888 which is 4 bytes per pixel.

If you use RGB_565 color channel which use 2 Bytes per pixel. half the memory allocation for same resolution :)

  1. Use inBitmap property for recycling purpose.

  2. Do not make static Drawable Object as it cannot be garbage collected.

  3. Request large heap in in manifest file.

  4. Use multiple processes if you are doing lot of image processing(memory intensive task) or use NDK (Native Development using c, c++)

Solution 4

You can try calling recycle() on the bitmap when you are done with it. This will clear all the image data and free up the memory. If anything tries to draw the bitmap after this then your app will crash. If you do get a crash it may help you find out what is still holding onto your bitmap.

Solution 5

This happens because you are loading the bitmap directly,which consumes a lot of memory. Instead use a scaled down version of the picture in _profileBitmap. This guy explains it pretty well. http://androidcocktail.blogspot.in/2012/05/solving-bitmap-size-exceeds-vm-budget.html

Solution 6

With Larger images it can be avoided by sampling them into smaller size. Use below example -

    File f = new File(selectedImagePath); 

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f), null, options); 
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, 720, 1280); //My device pixel resolution
    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;    
    Bitmap bmpPic = BitmapFactory.decodeStream(new FileInputStream(f), null, options); 


    Bitmap bmpPic1 = Bitmap.createBitmap(bmpPic, 0, 0, bmpPic.getWidth(), bmpPic.getHeight(), mat, true);   
    img.setImageBitmap(bmpPic1);  //img is your ImageView

Reference- http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

Solution 7

You could use a vector Drawable . It uses an xml file to describe your image , so it consumes less memory. To do that you should use the SVG format for your images and then generate the xml file using one of these 2 solutions :

  • Solution 1 : Use the vector asset studio in Android Studio : right click on Drawable file in your project -> new -> vector asset
  • Solution 2 : Use the svg2android website : https://inloop.github.io/svg2android

Check out this link for further information:
https://developer.android.com/studio/write/vector-asset-studio.html

Solution 8

I had the same issue when the phone was powered off and back on. Simply setting the bitmaps to null and calling System.gc(); fixed all the problems.

Solution 9

I had this issue because I was modifying a bitmap once, and then modifying the modified version a second time, resulting in three versions of the same bitmap (original, plus the two modified versions) being in memory at the same time.

I fixed it by changing my image-editing code to apply both modifications to the same bitmap as a kind of batch process, halving the number of modified versions that my app had to hold in memory.