Decode bitmaps in Android with the right size

I decode bitmaps from an SD card using BitmapFactory.decodeFile . Sometimes bitmaps are larger than what the application requires or what the heap allows, so I use BitmapFactory.Options.inSampleSize to request a subsample of a (smaller) bitmap.

The problem is that the platform does not provide the exact value of inSampleSize, and sometimes I get the bitmap too small or still too large for the available memory.

From http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize :

Note: the decoder will try to fulfill this request, but the received bitmap may have different sizes, which are exactly what was requested. In addition, powers 2 are often faster / easier for an honor decoder.

How do I decode bitmaps from an SD card to get the exact size bitmap that I need, consuming as little memory as possible to decode it?

Edit:

Current Source Code:

 BitmapFactory.Options bounds = new BitmapFactory.Options(); this.bounds.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, bounds); if (bounds.outWidth == -1) { // TODO: Error } int width = bounds.outWidth; int height = bounds.outHeight; boolean withinBounds = width <= maxWidth && height <= maxHeight; if (!withinBounds) { int newWidth = calculateNewWidth(int width, int height); float sampleSizeF = (float) width / (float) newWidth; int sampleSize = Math.round(sampleSizeF); BitmapFactory.Options resample = new BitmapFactory.Options(); resample.inSampleSize = sampleSize; bitmap = BitmapFactory.decodeFile(filePath, resample); } 
+58
android memory bitmap sd-card
Apr 14 '10 at 23:22
source share
10 answers

You are on the right track, however you are trying to do two things at once: read the file and scale it to the right size.

The first step is to read the file in the bitmap a little more than you need using BitmapFactory.Options.inSampleSize to make sure you do not consume excessive memory reading a large bitmap when all you need is a smaller thumbnail or screen resolution picture.

The second step is to call Bitmap.createScaledBitmap () to create a new bitmap with the required resolution.

Make sure you clear after the temporary bitmap to restore its memory. (Either let the variable go out of scope and let the GC handle it, or call it .recycle () if you upload a large number of images and work tightly in memory.)

+44
Jul 29 '10 at 16:57
source share

You can use inJustDecodeBounds . Set it to TRUE and upload the file as is.

The image will not be loaded into memory. But the outheight and outwidth properties of BitmapFactory.Options will contain parameters for the actual size of the specified image. Calculate how much u want the subquery. i.e. 1/2 or 1/4 or 1/8, etc. and assign 2/4/8 etc., respectively, in inSampleSize .

Now set inJustDecodeBounds to FALSE and call BitmapFactory.decodeFile() to load the exact size image calculated above.

+15
Apr 17 2018-10-17 at
source share

First you need to try the image to the nearest sample value so that the bitmap becomes efficient from the point of view of memory, which you perfectly described. After that, you can scale it to fit your screen.

 // This function taking care of sampling backImage =decodeSampledBitmapFromResource(getResources(),R.drawable.back, width, height); // This will scale it to your screen width and height. you need to pass screen width and height. backImage = Bitmap.createScaledBitmap(backImage, width, height, false); 
+6
Jun 03 '12 at 8:22
source share

Because the API already states that the sample size may or may not be performed. So I think ur due to luck when using BitmapFactory .

But the output will use your own bitmap reader. But I would advise you to stick with BitmapFactory, as it is fairly well tested and standardized.

I would try and not be too worried about the small excess memory consumption, but try to find out why it does not comply with the values. Unfortunately, I do not know about this :(

+1
Apr 18 '10 at 14:20
source share
 ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filesPath), THUMBSIZE, THUMBSIZE)) 

You can directly set THUMBSIZE depending on your requirement, however I'm not sure about the details of lower level implementation, image output quality and its performance, but I usually prefer it when I need to show a sketch.

+1
Jan 25 '14 at 6:49
source share

For those who are looking for the exact size of the image from the resources.

For the exact width pass reqHight = 0 and for the exact passage of the height reqWidth = 0

 public static Bitmap decodeBitmapResource(Context context, int resId, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(context.getResources(), resId, options); float scale = 1; if (reqWidth != 0 && reqHeight == 0) { options.inSampleSize = (int) Math.ceil(options.outWidth / (float) reqWidth); scale = (float) options.outWidth / (float) reqWidth; } else if (reqHeight != 0 && reqWidth == 0) { options.inSampleSize = (int) Math.ceil(options.outHeight / (float) reqHeight); scale = (float) options.outHeight / (float) reqHeight; } else if (reqHeight != 0 && reqWidth != 0) { float x = (float) options.outWidth / (float) reqWidth; float y = (float) options.outHeight / (float) reqHeight; scale = x > y ? x : y; } reqWidth = (int) ((float) options.outWidth / scale); reqHeight = (int) ((float) options.outHeight / scale); options.inJustDecodeBounds = false; Bitmap tmp = BitmapFactory.decodeResource(context.getResources(), resId, options); Bitmap out = Bitmap.createScaledBitmap(tmp, reqWidth, reqHeight, false); tmp.recycle(); tmp = null; return out; } 
+1
Aug 02 '16 at 7:32
source share

Since I use inSampleSize, I no longer run into memory issues. Therefore, inSampleSize works stably enough for me. I would recommend you double-check the problem. The size may not be the same as you requested. But it still needs to be reduced, and there should be no more "Not enough memory." I also recommend posting a code snippet here, maybe something is wrong.

0
Apr 21 '10 at 15:09
source share

As 100rabh said, if you use BitmapFactory, you really don't have much choice. However, bitmap decoding is really simple, and depending on the scaling algorithm you want to use, it is usually quite simple to scale it on the fly without having to read large portions of the original bitmap into memory (in general, you will only need to double the amount of memory needed for 1-2 lines of the original bitmap).

0
Apr 22 2018-10-22T00:
source share

When the inScaled flag is set (TRUE by default), if inDensity and inTargetDensity are not 0, the bitmap will scale according to inTargetDensity when loading, instead of relying on the graphics system to scale it every time it is drawn on canvas. So just set the inScaled value to false.

 BitmapFactory.Options options = new BitmapFactory.Options(); options.inScaled = false; 
0
Dec 25 '16 at 16:40
source share

I was able to approximately get the β€œcorrect size” by changing the size of the decoded image file to 70% of its bitmap size.

 Bitmap myBitmap = BitmapFactory.decodeFile(path); if(myBitmap != null) { //reduce to 70% size; bitmaps produce larger than actual image size Bitmap rescaledMyBitmap = Bitmap.createScaledBitmap( myBitmap, myBitmap.getWidth()/10*7, myBitmap.getHeight()/10*7, false); image.setImageBitmap(rescaledMyBitmap); } 

Hope this helps you somehow! Peace!

0
Apr 04 '17 at 3:14
source share



All Articles