Decoding bitmaps in Android with the right size

2019-01-04 21:08发布

I decode bitmaps from the SD card using BitmapFactory.decodeFile. Sometimes the bitmaps are bigger than what the application needs or that the heap allows, so I use BitmapFactory.Options.inSampleSize to request a subsampled (smaller) bitmap.

The problem is that the platform does not enforce the exact value of inSampleSize, and I sometimes end up with a bitmap either too small, or still too big 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 resulting bitmap may have different dimensions that precisely what has been requested. Also, powers of 2 are often faster/easier for the decoder to honor.

How should I decode bitmaps from the SD card to get a bitmap of the exact size I need while 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);
}

10条回答
来,给爷笑一个
2楼-- · 2019-01-04 21:37

Since the API already states that the sample size may or may not be honored. So I guess ur out of luck while using BitmapFactory .

But the way out would be using your own bitmap reader. But I would suggest that you stick with BitmapFactory as its fairly well tested and standardized.

I would try and not worry too much about little extra memory consumption, but try and find out why its not honoring the values. Sadly I have not idea about that :(

查看更多
3楼-- · 2019-01-04 21:41

First you need to sample the image to nearest sampling value so that bitmap become memory efficient, which you have described perfectly. Once it's done you can scale it up 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); 
查看更多
Juvenile、少年°
4楼-- · 2019-01-04 21:43

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

The first step is to read the file to a Bitmap slightly bigger than you require, using BitmapFactory.Options.inSampleSize to ensure that you do not consume excessive memory reading a large bitmap when all you want is a smaller thumbnail or screen resolution image.

The second step is to call Bitmap.createScaledBitmap() to create a new bitmap to the exact resolution you require.

Make sure you clean up after the temporary bitmap to reclaim its memory. (Either let the variable go out of scope and let the GC deal with it, or call .recycle() on it if you are loading lots of images and are running tight on memory.)

查看更多
仙女界的扛把子
5楼-- · 2019-01-04 21:44

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

查看更多
ら.Afraid
6楼-- · 2019-01-04 21:47
ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(filesPath), THUMBSIZE, THUMBSIZE))

You can directly set the THUMBSIZE depending upon your requirement,however i am not sure about the lower level implementation details,output image quality and its performance but i usually prefer it when i need to show thumbnail.

查看更多
不美不萌又怎样
7楼-- · 2019-01-04 21:50

I was able to approximately get the "right size" by rescaling the decoded image file to 70% 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);
}                

I hope this helps you out somehow! Peace!

查看更多
登录 后发表回答