What is the most efficient way to resize bitmaps on Android?

Asked

Viewed 818 times

1

When a device has smaller screen resolutions, you need to resize the bitmaps to optimize its display on the display properly.

The problem is that the use of createScaledBitmap can generate a lot of memory loss errors after resizing a set of small images.

What is the most efficient way to resize bitmaps on Android?

  • Do you know the Picasso? For those who deal with image, it is an essential library. Maybe he even optimises all this for you, I don’t know.

2 answers

4

This answer is summarized from the article Loading large bitmaps Efficiently, which explains how to use inSampleSize to carry a bitmap low-scale

In particular, Pre-scaling bitmaps explains the details of various methods, including how to combine them, and which ones are more efficient for device memory.

There are three dominant paths to resize a bitmap on Android, where each has different memory properties:

createScaledBitmap API

This API will take on an existing bitmap and create a NEW bitmap with the exact dimensions you selected.

On the plus side, you can get exactly the image size you are looking for. The downside is that this API requires a bitmap existing to work. That is, the image would have to be loaded, decoded and a bit map created, before being able to create a new version , smaller .

This procedure is ideal for obtaining its exact dimensions , but horrible in terms of additional memory overload. Most application developers who tend to worry about memory avoid using this method.

inSampleSize flag

BitmapFactory.Options has a property referenced as inSampleSize which will resize your image and decode it at the same time, to avoid the decoding process for a bitmap temporary.

The value whole used here will load the image reducing to half its size. Basically, the result will always be a factor of 2 times smaller than your source image.

When we talk about memory, inSampleSize is an extremely fast operation. Effectively, it will decode every pixel of your image. However, there are two major problems when using inSampleSize:

  • You will not have exact resolutions. This function only reduces the size of your bitmap by a factor of 2.

  • This function does not produce the best resizing quality. Many resize filters produce great-looking images by reading pixel blocks, and then weighing them to produce the pixel in question. inSampleSize avoids all this just by reading each pixel. The result is high performance and low memory, but the quality remains to be desired.

If you are only dealing with reducing your image by a small factor, and filtering is not a problem, then you will not find such an efficient method of memory as the inSampleSize.

inScaled, inDensity, inTargetDensity flags

If you need to resize an image to a dimension that is not reachable with the factor of 2, then you will need to use the flags of the BitmapOptions: inScaled, inDensity and inTargetDensity. When inScaled is set, the system will fetch the appropriate scale value to apply to your bitmap by dividing the values of inTargetDensity for inDensity.

mBitmapOptions.inScaled = true;
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity =  dstWidth;

// este método carrega e redimensiona a imagem para a dimensão de 1/inSampleSize
mCurrentBitmap = BitmapFactory.decodeResources(getResources(), 
      mImageIDs, mBitmapOptions);

Using this method will resize your image and also apply a resize filter. The result will apparently be much better due to the additional math involved during the resize step. But pay attention: This extra step requires longer processing time, and can quickly solve problems for large images resulting in smaller dimensions and extra memory allocation for the filter.

It is generally not a good idea to apply this technique to an image that is significantly larger than the desired size due to the extra cost of filter memory.

Combining Memory and Performance

From the point of view of memory and performance, it is possible combine these options for best results. (Setting the flags inSampleSize, inScaled, inDensity and inTargetDensity).

inSampleSize will be the first to be applied to the image, making it close to the factor of 2 times larger than the target size. Then, inDensity & inTargetDensity will be used to scale the result to the exact dimensions you want, applying an operation filter to clean the image.

Combining these two makes the operation much faster, since inSampleSize will reduce the number of pixels where the filter needs to be applied.

mBitmapOptions.inScaled = true;
mBitmapOptions.inSampleSize = 4
mBitmapOptions.inDensity = srcWidth;
mBitmapOptions.inTargetDensity =  dstWidth * mBitmapOptions.inSampleSize;

// carrega e redimensiona a imagem para ser da dimensão de 1/inSampleSize
mCurrentBitmap = BitmapFactory.decodeFile(fileName, mBitmapOptions);

If you need to fit an image into specific dimensions and adding good image filters, so this technique is the best way to get the correct size, but done quickly and consuming little memory during operation.

Getting the image dimensions

Getting the image size without having to decode it completely.

To be able to resize your bitmap, you will need to know the input dimensions. You can use the flag inJustDecodeBounds to help you take the image dimensions without the need to decode the data.

mBitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fileName, mBitmapOptions);
srcWidth = mBitmapOptions.outWidth;
srcHeight = mBitmapOptions.outHeight;

// agora redimensione a imagem para o tamanho que você deseja

You can use this flag to decode the size first, then calculate the appropriate values to scale the resolution of your target image.

-1

After having your bitmap created, resize with the method createScaledBitmap(). Ex:

// Cria o objeto
Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
// Redimensiona para 60 x 80 px
bmp = Bitmap.createScaledBitmap(bmp, 60, 80, false);
  • You read the question? The use of createScaledBitmap can generate a lot of memory loss errors after resizing a set of small images.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.