0

I am getting OutOfMemoryError on BitMap while calling Bitmap.createScaledBitmap

I already tried to recycle and setting to null to the BitMap reference, but still stucked.

Code which I am using is

private Bitmap getImageBitmap(float startX, float startY, float currX, float currY, Resources res, int resId) {
    Bitmap bitSrc = BitmapFactory.decodeResource(res, resId);
    int dstWidth = (int) ((Math.abs((currX - startX)) + 1));
    int dstHeight = (int) ((Math.abs((currY - startY)) + 1));
    Bitmap bitImg = Bitmap.createScaledBitmap(bitSrc, dstWidth, dstHeight, false);
    bitSrc = null;
    return bitImg;
}

I am setting the returned bitImg on canvas. Here is my Log file

    08-14 13:31:14.364: E/AndroidRuntime(6714): java.lang.OutOfMemoryError
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.graphics.Bitmap.nativeCreate(Native Method)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.graphics.Bitmap.createBitmap(Bitmap.java:809)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.graphics.Bitmap.createBitmap(Bitmap.java:786)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.graphics.Bitmap.createBitmap(Bitmap.java:718)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:594)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at com.example.layout.Drawing.getImageBitmap(DrawingSurface.java:856)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at com.example.layout.Drawing.onDraw(DrawingSurface.java:291)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.draw(View.java:14465)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13362)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13404)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3077)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13300)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13404)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3077)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13300)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13404)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3077)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13300)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13404)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3077)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13300)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13404)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3077)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13300)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.View.getDisplayList(View.java:13404)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.HardwareRenderer$GlRenderer.buildDisplayList(HardwareRenderer.java:1626)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1505)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewRootImpl.draw(ViewRootImpl.java:2460)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2332)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1962)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1079)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5784)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:774)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.Choreographer.doCallbacks(Choreographer.java:587)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.Choreographer.doFrame(Choreographer.java:550)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:760)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.os.Handler.handleCallback(Handler.java:733)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.os.Handler.dispatchMessage(Handler.java:95)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.os.Looper.loop(Looper.java:136)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at android.app.ActivityThread.main(ActivityThread.java:5017)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at java.lang.reflect.Method.invokeNative(Native Method)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at java.lang.reflect.Method.invoke(Method.java:515)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
08-14 13:31:14.364: E/AndroidRuntime(6714):     at dalvik.system.NativeStart.main(Native Method)

Thanks in advance.

Rahul Patidar
  • 406
  • 3
  • 12

4 Answers4

1

It's not because of recycling or setting null bitmap. It's because your Image is too large. as I can see from your code:

Bitmap bitSrc = BitmapFactory.decodeResource(res, resId);

You load large Bitmap once, then Bitmap.createScaledBitmap(bitSrc, dstWidth, dstHeight, false); you load it another times. That mean you load 2 times your large Image --> That's the reason why you got outofmemory exception.

To solve it, you can visit Loading Large Bitmap effeciently to learn how to scale down your bitmap before displaying it.

Kingfisher Phuoc
  • 8,052
  • 9
  • 46
  • 86
0

I do not know what you are trying to achieve, but I would advise you to use a library, for example http://square.github.io/picasso/. Loading and handling bitmaps in Android can be difficult and time consuming. With this library you get caching etc for free.

How large is your bitmap? You can do all sorts of optimizations, as explained in the links given to you in the comments. For example: reduce image size (from what I can see you are loading the Bitmap full size in the first line), reduce color space (if you dont need an alpha-channel for example, that will save you a few bytes). Take a look at http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html for options on how to optimize your Bitmap-loading according to your use.

Again I would advise you to use a library in which all these issues are solved, Bitmaps in Android are difficult.

Kenneth
  • 3,957
  • 8
  • 39
  • 62
0

Check out the developer guide about this issue: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

It states you have to get the dimensions of the Bitmap by adding BitmapFactory.Options that loads the dimensions but not the bitmap itself. With these dimensions you can calculate the scale size of the bitmap you need. Add that scale to BitmapFactory.Options and load the bitmap in the right size.

dumazy
  • 13,857
  • 12
  • 66
  • 113
0

I believe this is because even the Bitmap you loading is way large for the device you test your project on or you don't get rid of used Bitmaps so that you have overloaded bitmaps, or even you have both problems, So, when accessing a device with low memory consider scaling your bitmap to meet the memory conditions of that device, according to my answer here you have to use the following way to scale your Bitmap(you didn't post the way you using):

// to scale your Bitmaps
// assign newWidth and newHeight with the corresponding width and height that doesn't make your memory overloads and in the same time doesn't make your image loses it's Features
private Bitmap scaleBitmap(Bitmap bitmapToScale, float newWidth, float newHeight) {

    if(bitmapToScale == null)
        return null;
    //get the original width and height
    int width = bitmapToScale.getWidth();
    int height = bitmapToScale.getHeight();
    // create a matrix for the manipulation
    Matrix matrix = new Matrix();

    // resize the bit map
    matrix.postScale(newWidth / width, newHeight / height);

    // recreate the new Bitmap and set it back
    return Bitmap.createBitmap(bitmapToScale, 0, 0, bitmapToScale.getWidth(), bitmapToScale.getHeight(), matrix, true);  

}

and get rid of used resources like the following:

bitSrc.recycle(); you source Bitmap
stream.close(); // if you used to load the Bitmap
stream = null;
bitmap.recycle(); // your used Bitmap after using it
Community
  • 1
  • 1
Muhammed Refaat
  • 8,914
  • 14
  • 83
  • 118