Sunday 10 February 2013

OutOfMemoryError: bitmap size exceeds VM budget - Android

Bitmap out of memory is a common problem in android, it took lot of time for me to solve this issue.
Like i tried catching this error, which did work to some extent but couldn't solve my problem totally.

Hence, i started digging into it from low level. Basically android system allocates memory for each application, which varies from device to device, min16 MB to max 90MB(google Nexus 7). 

Now, when ever free memory out of allocated memory for an app is less then Bitmap size, System throws Out of Memory error, if bitmap size is more then free memory then we should not load the image. So I ended up finding the size of bitmap and free memory available, which can be checked using below code.

  public static boolean checkBitmapFitsInMemory(long bmpwidth, long bmpheight, int bitdepth) {
    long reqsize = 
bmpwidth x bmpheight x (bitdepth) / 8;
    long allocNativeHeap = Debug.getNativeHeapAllocatedSize();

    final long heapPad = (long) Math.max(3 * 1024 * 1024, Runtime.getRuntime()
        .maxMemory() * 0.1);
    if ((reqsize + allocNativeHeap + heapPad) >= Runtime.getRuntime()
        .maxMemory()) {
      return false;
    }
    return true;

  }


Here calculating image size properly is very important, if a image file size is 250kb it dose not mean that it will take 250kb in memory, that is the file size in disk. When the image is loaded in memory(RAM) it will calculate the pixels of the image and for example if you take RGB image for each color it will take 8 bit of memory that meant red + green + blue = 24 bit for each pixel, convert 24 bit into byte it is 3 byte for single pixel now calculate how many pixels are there in image (width pixels x height pixels) you will get total pixels of the image then multiply total pixels of the image with 3 if it is RGB image and you will get total memory required to load the image in memory if there is less memory then don't load the image to avoid OutOfMemoryError.
if your image have alpha channel (RGBA) then for each pixel it will take 4 byte. For Gray scale (black and white) image it will take 2 byte.