1

I am trying to load an image in my app having size 495KB. If I load this image than heap size increases from 25MB to 35MB which is causing real memory issues in my app. If i dont load this image than heap size stays at 25MB. Can anybody tell why it is taking so much heap size?

Image is below enter image description here

Code that I am using to load an image is

    InputStream s4 = getResources().openRawResource(R.drawable.parallax_layer4);    
    FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
    System.gc();
    if(bitmap4 != null) {
        bitmap4.recycle();
    }
    s3 = null;
    System.gc();     

    bitmap4 = bitmap(s4);
    layer4Back = new ImageView(this);
    layer4Back.setImageBitmap(bitmap4);
    layer4Back.setScaleType(ScaleType.FIT_XY);
    parallaxLayout.addView(layer4Back, 3, lp);
    try {
        s4.close();
    } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
    }
    s4 = null;
    System.gc();

private static Bitmap bitmap(final InputStream is) {
    Bitmap bitmap = null;
    System.gc();
    Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    options.inSampleSize = 1; 

    try {
       // bitmap = BitmapFactory.decodeStream(is);
       bitmap = BitmapFactory.decodeStream(is, null, options);

    } catch (Error e) {
       // TODO: handle exception
       e.printStackTrace();
    }
    return bitmap;
}

Thanks Ayaz Alavi

trincot
  • 317,000
  • 35
  • 244
  • 286
Ayaz Alavi
  • 4,825
  • 8
  • 50
  • 68

4 Answers4

5

The image file is uncompressed when it's loaded into memory. At 5600 x 480 pixels and 32 bits per pixel, your image works out as almost exactly 10 MB when uncompressed.

My recommendation would be to cut it into smaller sections and only load the sections you need.

grahamparks
  • 16,130
  • 5
  • 49
  • 43
  • If i remove some of the flowers inbetween will this cause any change? I have to use complete image as one. – Ayaz Alavi Jul 06 '12 at 07:25
  • The amount of memory used is directly proportional to the pixel size of the image, so anything you do to reduce is size will directly reduce the memory consumption. (Changing the content won't help) – grahamparks Jul 06 '12 at 07:48
2

5,600px * 480px * 4 bytes = 10,752,000 bytes, so this isn't surprising.

There is some good guidance in the Displaying Bitmaps Efficiently article, as well as quite a few questions here on SO discussing good solutions.

Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109
  • If remove some of the flowers in between and keep my image size as 5600 * 480, will memory consumption will be same? – Ayaz Alavi Jul 06 '12 at 07:26
  • What alternate solution do I have? – Ayaz Alavi Jul 06 '12 at 07:27
  • @AyazAlavi It doesn't matter what the pixel values are once it's uncompressed, which is what we're talking about. So no, removing flowers and maintaining the same dimensions won't make any difference. However, the link I pointed out has a lesson called "Loading Large Bitmaps Efficiently" which really explains things very well, better than I could do justice to here. – Darshan Rivka Whittle Jul 06 '12 at 07:30
  • What if I use RGB_565 in options. I see here http://developer.android.com/reference/android/graphics/Bitmap.Config.html that it will multiply by 2 instead of 4 but I see only ~2mb decrease in memory consumption. Why is that? (See updated code of bitmap() method in question) – Ayaz Alavi Jul 06 '12 at 08:07
  • options.inPreferredConfig = Bitmap.Config.RGB_565; – Ayaz Alavi Jul 06 '12 at 08:15
  • @AyazAlavi I'm not sure why that doesn't make a bigger difference, but that's really not the best solution, anyway. There's no way to display that whole image at scale and at once on any Android device. Either scale it down (or set `options.inSampleSize` to something like 3 or 4) or, as @grahamparks suggested, break it into smaller tiles and only use what you need when you need it. – Darshan Rivka Whittle Jul 06 '12 at 08:42
1

Well what did you expect? The image is 5600 x 480 px, now in memory every single pixel takes 32 bits (plz correct me someone). Do the math and you get a good idea why it is a problem. You need to use a smaller image OR cut the image up in parts and load the parts that is needed when they are needed and discard the unnecessary parts.

I had a similar problem which is discussed here: Android app crash out of memory on relaunch

There is also a long discussion about the subject and possible solutions here: Strange out of memory issue while loading an image to a Bitmap object

Community
  • 1
  • 1
Warpzit
  • 27,966
  • 19
  • 103
  • 155
0

BitmapFactory will auto-scale your bitmap if you load it and have a high DPI screen resolution. I think on devices with the largest DPI value it gets scaled by 2x in both directions.

This may explain some of the unexpected increase. Try putting your images in folder called drawable-nodpi and they will not be scaled.

Tim
  • 35,413
  • 11
  • 95
  • 121