3

In my activity I am creating a Bitmap of the width and height same as the device resolution (width and height )

what I am doing

Bitmap mBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);

and screenWidth and screenHeight is

    screenHeight = displaymetrics.heightPixels;
    screenWidth = displaymetrics.widthPixels;

Now if I make this bitmap I get my heap goes up to 19mb , which is not so good.

So tell me 2 things

1. What is a good way of creating the bitmap with respect to screen with and height with minimum memory consumed

2. How can I destroy the bitmap after using it ?

Please provide me a little source code or link of source code.

Coas Mckey
  • 701
  • 1
  • 13
  • 39
  • you might want to check this video https://www.youtube.com/watch?v=HY9aaXHx8yA – Luis Pereira Oct 28 '15 at 13:58
  • 1
    @iGoDa By reading developer site I am exactly understand this , but I want the solution according to my need, I want to get bitmap of screen size mean while it should be at its minimum size – Coas Mckey Oct 28 '15 at 14:06
  • You can destroy the bitmap by calling destroyDrawingCache() method.For example:iv.destroyDrawingCache() or frame.destroyDrawingCache().Here iv and frame are ImageView and FrameLayout respectively. – Nitesh Oct 28 '15 at 14:07

1 Answers1

3
  1. What is a good way of creating the bitmap with respect to screen with and height with minimum memory consumed ?

    1. Never ever create a Bitmap with the screen height or width, because that will be very huge based on the density of the device.Instead use the height and width of the screen and calculate the aspect ratio. Now fix the height to a constant value (like 1200px) and then calculate the width based on the aspect ratio. The ImageView or any other view will scale this properly.
    2. If you really want transparency then use Bitmap.Config.ARGB_8888, if not could use RGB_565 or something else from the list here: http://developer.android.com/reference/android/graphics/Bitmap.Config.html
    3. Follow below points if you are not creating a fresh bitmap but decoding the bitmap from some resource:
      1. You need to use BitmapFactory.Options.inSampleSize to reduce the sampling. So how to calculate the inSampleSize if you already know the height and width? Refer this here: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
      2. So you do all this, and still the inSampleSize is not high enough and you get the OutOfMemoryError ? Don't worry, if this is the case, you need to catch this OutOfMemoryError and in that increase your inSampleSize and do the bitmap decode again. Put this logic in a loop, so the crash never happens.

  2. How can I destroy the bitmap after using it ?

    1. This is really simple. Make sure to call the Bitmap.recycle() method. And remove all reference to the bitmap. Once you do this, the resource will be released and GC will do the cleaning up.

UPDATE: When you create the a bitmap with screen_width and screen_height you would end up with a huge bitmap. Instead create a less resolution bitmap that fits the whole screen. You can see the following code on how this is done.

    float screenHeight = displaymetrics.heightPixels;
    float screenWidth = displaymetrics.widthPixels;

    float aspectRatio  = screenWidth/screenHeight;

    int modifiedScreenHeight = 1000;
    int modifiedScreenWidth = (int) (modifiedScreenHeight * aspectRatio);

    Bitmap mBitmap = Bitmap.createBitmap(modifiedScreenWidth, modifiedScreenHeight, Bitmap.Config.ARGB_8888);

Now you got the bitmap with the right aspect ratio. You could use this bitmap as it is in the ImageView to fill the whole screen. Make sure you put android:scaleType="fitXY" for the ImageView.

Henry
  • 17,490
  • 7
  • 63
  • 98
  • can you please eloborate what do you mean by never create a Bitmap with the screen height or width but use the height and width of the screen and calculate the aspect ratio. – Coas Mckey Oct 29 '15 at 06:11
  • I want to make a bitmap which expend to all over the width and height of screen ? what would you suggest , please explain with code ,, Please – Coas Mckey Oct 29 '15 at 06:12
  • thats great , but one point is still not clear for me .. you are making this int modifiedScreenHeight = 1000; How come Do we know that this is right height for all devices ? – Coas Mckey Oct 29 '15 at 07:34
  • This 1000 is not about the height of the screen, but the resolution of the image. You need to select this value based on the memory you afford. I believe that a 1200px width or height image looks good in all phones. – Henry Oct 29 '15 at 08:31
  • by doing this , I got the following error Caused by: java.lang.IllegalArgumentException: width and height must be > 0 – Coas Mckey Oct 29 '15 at 08:51
  • Yes ideally it should be. I think your `screenWidth` and `screenHeight` are in `int` data type. Hence when you divide them, `aspectRatio` will be 0. So make them as `float` data type. You should make sure that `aspectRatio` is not 0. – Henry Oct 29 '15 at 08:56
  • yeah , I just debug that and found the same reason you told , i predict the same – Coas Mckey Oct 29 '15 at 09:00
  • last question , lower the modifiedScreenHeight would lower the bitmap size and also size in heap ? or it would increase – Coas Mckey Oct 29 '15 at 09:02
  • lowering the `modifiedScreenHeight` or `modifiedScreenWidth` will lower the bitmap size, this in turn will lower the heap size. – Henry Oct 29 '15 at 09:05
  • and it will cover all screen though its resolution is not good though it not look good? – Coas Mckey Oct 29 '15 at 09:12
  • My main concern is to fill the screen , and get minimum heap size , no matter how bad does it looks – Coas Mckey Oct 29 '15 at 09:12
  • 1000 will look good in all phones. If you are going for a tablet then you could go a bit higher. It all depends on the `screenWidth` and `screenHeight`. I usually would calculate the `modifiedSceenWidth` as `min(screenWidth/2, 1000)`. The lower value you choose for `modifiedScreenHeight`, the lower the quality of the image will be, but heap size will be less. If you don't care about the quality, then go ahead with 1000 or less. – Henry Oct 29 '15 at 09:16
  • well henry how about after creating this bitmap , then scaling it before loading into memory , how about that ? – Coas Mckey Oct 29 '15 at 09:21
  • The moment you create the `bitmap`, it's loaded in memory and hence your heap size will increase. You could then scale it and use that and `recyle()` the initial `bitmap`. Once GC gets called, your heap size will decrease again. – Henry Oct 29 '15 at 09:24
  • oh thats a really good point , cant we create and scale it at the same time ? – Coas Mckey Oct 29 '15 at 09:26
  • No, you can't. Creation means memory allocation. So you need to create it with the right size. – Henry Oct 29 '15 at 09:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/93655/discussion-between-coas-mckey-and-henry). – Coas Mckey Oct 29 '15 at 09:30
  • I'm developing a game using Android canvas, and I need to create a bitmap the size of the screen, to draw the background of the game (the background is being drawn dynamically). Since allocating such huge size on a bitmap might cause an OutOfMemoryError, what's the best approach to do that? – steliosf May 13 '17 at 18:08
  • Do you really need a new bitmap? Try to draw directly on your custom view's canvas, rather than creating an additional bitmap. – Henry May 14 '17 at 08:04