Coas Mckey
Coas Mckey

Reputation: 709

How to create the bitmap and decode it at the same time

I am creating a bitmap and it takes about 11 mb in the heap , though it is of the small size. Well I wanted to know if I can create the bitmap and also sclae it as a same time. The reason I want to do it is , the memory allocation , as If I understand correctly from different bitmap questions which are posted here , and that is

The bitmap allocates the memory as when it is created

So if its , then scaling it again take some process time and also increase the heap size until and unless the garbage collection is not occurred

So what I am doing is

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

        int modifiedScreenHeight = 400;
        int modifiedScreenWidth = (int) (modifiedScreenHeight * aspectRatio);
        mBitmap = Bitmap.createBitmap(modifiedScreenWidth, modifiedScreenHeight, Bitmap.Config.ARGB_8888);

So now it is creating the bitmap and allocation the memory , by memory analyzer tool in android studio I can see that it took 11mb in memory.

But I want to minimize them ,I have visited a link and I want to do some more scaling by options as show in this video . but it uses the file to decode such as

BitmapFactory.decodeFile(??,options);

where as I have no file to decode from , I want to decode it from the bitmap I created and to wash away the last created bitmap to clear the memory.

Or if it is possible to set the options when creating it so that we can avoid from extra memory allocation .

Please help.

Upvotes: 0

Views: 235

Answers (1)

Gil Moshayof
Gil Moshayof

Reputation: 16761

You can use this using BitmapFactory.Options - specifically, use the options to decode the width / height of the bitmap, then sampleSize to determine how large the generated bitmap will be.

According to your example, you'd like the width/height of the bitmap to be 400 by 400 * aspectRatio. So, first, you'll need to see how large the bitmap needs to be. Do this as so:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

BitmapFactory.decodeFile(??, options);

int bitmapWidth = options.outWidth;
int bitmapHeight = options.outHeight;

This action will only decode the bitmaps size, without actually allocating memory for the bitmap's pixels. This is good because it's a very quick and light operation which doesn't require much resources and helps you make a more educated decision when loading the bitmap. Now we must use these size to determine how big the generated bitmap will be.

int sampleSize = 1;

while (bitmapWidth / sampleSize > 400 && bitmapHieght / sampleSize > 400 * aspectRatio)
    sampleSize *= 2;

sampleSize must be a power of 2 for this to work, and what it will do is determine how many pixels to "skip" when reading the bitmap into memory. This algorithm will set a sample size to a size equal to 1st sample size which will produce a bitmap immediately smaller than the required bounds. You can tweak this if you'd like a slightly different implementation.

Now that you have the sample size, set it with in the options object and load the actual bitmap:

options.inJustDecodeBounds = false;
options.inSampleSize = sampleSize;

Bitmap bitmap = BitmapFactory.decodeFile(??, options);

The generated bitmap will be smaller than the required bounds, thus limiting your memory requirements for creating the bitmap object.

Hope this helps.

Upvotes: 1

Related Questions