3

During runtime, I am trying to put an image in the surface view. When I tried using the image from the Drawable folder I got Out of memory error. After a quick search in the stackoverflow, I found that there will be some relief if we access the image from the asset folder. But still I get the Out of memory error during runtime.

I have analyzed and found that scaling will help in resolving this kind of memory related issues. The thing is that I have the image size of 1280 x 720 and the device size also the same. Hence I feel like the scaling will not have any effect.

As we have experts in this community, I would appreciate if you can help me with some suggestions/examples to resolve this kind of issue.

Scenario 1:

Using the Bitmap from Drawable folder.

backgoundImage = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.backgroundhomepage), (int) dWidth, (int) dHeight, true);

    /***********************************************************************************************************************************************************
    1.  To get the image from asset library
     **************************************************************************************************************************************************************/ 

    public  Bitmap getAssetImage(Context context, String filename) throws IOException {
        AssetManager assets = context.getResources().getAssets();
        InputStream buffer = new BufferedInputStream((assets.open("drawable/" + filename + ".png")));
        Bitmap bitmap = BitmapFactory.decodeStream(buffer);
        return bitmap;
    }

Scenario 2:

Using the Bitmap from Assets folder

backgoundImage = Bitmap.createScaledBitmap(getAssetImage(context,"backgroundhomepage"), (int) dWidth, (int) dHeight, true);
Kanwaljit Singh
  • 4,339
  • 2
  • 18
  • 21
iappmaker
  • 2,945
  • 9
  • 35
  • 76
  • i also had this problem. look here for the solution http://stackoverflow.com/questions/20817369/outofmemory-error-using-imageview/20817563#20817563 – George Lungu Dec 28 '13 at 18:02

3 Answers3

3

OutofMemory occurs when your app exceeds memory allocated in heap. The bitmap is too large to fit in memory ie heap. In such a case you run out of memory. You need to scale down the bitmap and then use the same. For that check the link below

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

There is also a blog @ http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html (avoiding memory leaks)

 public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
 try {
     //Decode image size
     BitmapFactory.Options o = new BitmapFactory.Options();
     o.inJustDecodeBounds = true;
     BitmapFactory.decodeStream(new FileInputStream(f),null,o);

     //The new size we want to scale to
     final int REQUIRED_WIDTH=WIDTH;
     final int REQUIRED_HIGHT=HIGHT;
     //Find the correct scale value. It should be the power of 2.
     int scale=1;
     while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
         scale*=2;

     //Decode with inSampleSize
     BitmapFactory.Options o2 = new BitmapFactory.Options();
     o2.inSampleSize=scale;
     return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
 } catch (FileNotFoundException e) {}
 return null;
}

Quoting from the docs

The BitmapFactory class provides several decoding methods (decodeByteArray(), decodeFile(), decodeResource(), etc.) for creating a Bitmap from various sources. Choose the most appropriate decode method based on your image data source. These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.Options class.

Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap.

Also check this link for memory management.

https://www.youtube.com/watch?v=_CruQY55HOk

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • Bitmap dimensions - 1280 x 720 and the size 127KB only and also the dimension of the device is same as the image size 1280 x 720. Any reason why we are scaling it ? – iappmaker May 27 '13 at 04:22
  • its too large and your app will exceed heap size allocated. hence you need to scale down. each device will have its own heap size. each app is allocated certain memory space in heap. If you exceed the allocated memory you are likely to run into memory leaks. What's the screen size and width? – Raghunandan May 27 '13 at 04:23
  • you mean to say 127 KB is tool large ? If I scale down will there be any significant change in the quality of the image ? – iappmaker May 27 '13 at 04:26
  • do you have any other images in your app? what is your screen height and width. – Raghunandan May 27 '13 at 04:27
  • @iappmaker you check the heap size. check the link http://developer.android.com/reference/android/app/ActivityManager.html#getMemoryClass%28%29 – Raghunandan May 27 '13 at 04:30
  • Yes another 4 images of 12 KB each. Device Spec - 720 x 1280 pixels, 4.3 inches (~342 ppi pixel density) – iappmaker May 27 '13 at 04:33
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/30664/discussion-between-raghunandan-and-iappmaker) – Raghunandan May 27 '13 at 04:34
2

Got a quick Solution

<application
     android:largeHeap="true" >

put into appplication tag in manifest file.

Nikhil Borad
  • 2,065
  • 16
  • 20
  • 1
    any side effects for this ? – iappmaker Jul 26 '15 at 02:52
  • 1
    The use of largeHeap is not recommended in all cases, please use it very cautiously, it might slow other running application, and also impact your app's reactiveness, since the garbage collector with be solicited more often. For more information check this speech from google i/o https://www.youtube.com/watch?v=_CruQY55HOk – Nikhil Borad Aug 01 '15 at 09:02
0

You can use the following code to load the bitmap from file:

private Bitmap decodeFile(File f,int req_Height,int req_Width){
    try {
        //decode image size
        BitmapFactory.Options o1 = new BitmapFactory.Options();
        o1.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o1);


        //Find the correct scale value. It should be the power of 2.
        int width_tmp = o1.outWidth;
        int height_tmp = o1.outHeight;
        int scale = 1;

        if(width_tmp > req_Width || height_tmp > req_Height)
        {
             int heightRatio = Math.round((float) height_tmp / (float) req_Height);
             int widthRatio = Math.round((float) width_tmp / (float) req_Width);


             scale = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        o2.inScaled = false;
        return BitmapFactory.decodeFile(f.getAbsolutePath(),o2);
    } 
    catch(Exception e) 
    {
      e.printStackTrace();
    }
    return null;
}

It should resolve your out of memory exception. Link here has a good detailed explanation of your answer.

Panky90
  • 148
  • 3
  • 10
  • Could you please explain what this is doing and why I should do this for the image of 720 x 1280 which is of the same size of my device ? – iappmaker May 27 '13 at 03:51
  • Have a look at this,it explains the issue very efficiently. http://developer.android.com/training/displaying-bitmaps/index.html – Panky90 May 27 '13 at 03:57
  • And the code above will subsample the image, loading a smaller version of it into memory. – Panky90 May 27 '13 at 04:01
  • @Panky90 you are loading a scaled down version into memory. Your bitmap may be too large and hence exceeds memory in heap leading to OOM. – Raghunandan May 27 '13 at 04:02
  • @Raghunandan yes thats what the link which I posted says, and also answers his question in detail. – Panky90 May 27 '13 at 04:06
  • @Panky90 posting link is fine but i suggest you post the important parts of the topic in the answer itself. Also explain in brief. – Raghunandan May 27 '13 at 04:14
  • @Raghunandan Ok I'll take that into consideration.Thanks for the suggestion, I'll just update this answer now.I thought the link has good easy description about his problem and is self explanatory,so i had avoided the explanation. – Panky90 May 27 '13 at 04:20