Android Bitmap compression strategy

First, why the need for efficient load Bitmap?

Now high-definition big picture, should easily several M, and Android memory limit imposed on individual applications, only a
small few dozen M, such as 16M, which causes a load Bitmapwhen it is prone to memory overflow. Abnormal letter as
interest rates, is often needed in development:

java.lang.OutofMemoryError:bitmap size exceeds VM budget

To solve this problem, there have been efficient loading strategy of Bitmap. In fact, the core idea is simple. The assumption
by ImageViewto display pictures, a lot of time ImageViewand not so much the size of the original picture,
this time to load the whole picture and then set to come in ImageView, apparently is not necessary, because
ImageViewthere is no way to display the original picture. This time can be reduced by a certain picture of the sample rate
and then loaded in, not only in this picture ImageViewis displayed, but also in a reduced memory footprint thereby
avoiding certain extent OOM, improved Bitmapperformance when loading

Second, efficient loading DETAILED Bitmap

1. The way to load the Bitmap

Android Bitmap in the middle is a picture. Four types of class provides methods BitmapFactory:
decodeFile, decodeResource, decodeStreamand decodeByteArray, respectively, from the file system,
loading the resource, and the byte array input stream a Bitmap object, which
decodeFile,decodeResourcein turn called indirect decodeStreammethods, four methods that ultimately
at the bottom of the Android achieved, corresponding to BitmapFactorya few native methods of the class.

2. BitmapFactory.OptionsParameters

inSampleSizeparameters of
the above-mentioned four types of methods support BitmapFactory.Optionsparameters, and Bitmapby a certain sampling rate reduction
release is through the BitmapFactory.Optionsparameters achieved, the main use of the inSampleSizeparameters, namely
the sampling rate. By inSampleSizesetting the height and width of the pixels of the picture to zoom.

When inSampleSize=1, that is, after sampling the picture size to the original size of the picture. Less than 1, but also according to a count
calculation. When inSampleSize>1, i.e., the sampled image will be reduced, at a scale of 1 / ( inSampleSize
the square).

For example: a 1024 × 1024 pixel image using ARGB8888 storage format, then the memory size of
1024 × 1024 × 4 = 4M. If inSampleSize=2, then the memory size of the sampled image:
512 × 512 ×. 4 = 1M.

Note: official document expenses, inSampleSizethe value should always be 2 index, such as 1,2,4,8 and so on.
If the incoming external inSampleSizevalue is not a power of two, the system will select a rounding down and
the index 2 is closest to replace. For example 3, the system will select 2 instead. Experience has shown that in all that time not
have been established on the Android version.

About inSampleSizeNote Value: The picture is usually based on the size of the actual width and height / width and height required
size, width and height were calculated zoom ratio. But should take the smallest zoom ratio, to avoid scaling the picture is too
small to reach the specified control can not be covered, you need to stretch leading to blurred.

For example: ImageView the size is 100 × 100 pixels, and the original image size is 200 × 300, then the width
of the zoom rate is 2, 3 is a high zoom ratio. If the final inSampleSize=2, then the scaled image size
100 × 150, is still appropriate ImageView. If inSampleSize=3, then the small picture size scaled
to the ImageViewdesired size, so the picture will be stretched and cause blurred.

inJustDecodeBoundsparameters
we need to get a load of the picture width and height information, and then to the inSampleSizeparameter select a zoom ratio shrink
release. So how can not load the picture was able to get the first pictures of width and height information through
inJustDecodeBounds=true, and then load the picture resolution can be achieved only picture width and height information, and
not the real picture is loaded, so this operation is lightweight. When acquiring a width and height information to calculate the scaling
back ratio, and then will inJustDecodeBounds=falsere-load the pictures, you can load the scaled
image.

Note: BitmapFactory the acquired image information and the image width of the high equipment and running positions are
off, such as with a picture in a different drawabledirectory, or run in different screen densities provided
on the apparatus, it may lead to BitmapFactoryacquired different results , and resource loading mechanism of Android
related

3. Efficient loading Bitmapprocess

① will be BitmapFactory.Optionsthe inJustDecodeBoundsparameter to true and Load picture.
② From the BitmapFactory.Optionstaken pictures of the original width and height information, which correspond to outWidthand
outHeightparameters.

③ According to the regular sampling rate and the required size of View binding target sample rate is calculated inSampleSize.
④ to BitmapFactory.Optionsthe inJustDecodeBoundsparameter set to false, then reload the
picture.

Third, Bitmapefficient loading of code to achieve

  public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight){
     BitmapFactory.Options options = new BitmapFactory.Options();
     options.inJustDecodeBounds = true;
     //加载图片
     BitmapFactory.decodeResource(res,resId,options);
     //计算缩放比
     options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);
     //重新加载图片
     options.inJustDecodeBounds =false;
     return BitmapFactory.decodeResource(res,resId,options);
  }

  private static int calculateInSampleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {
     int height = options.outHeight;
     int width = options.outWidth;
     int inSampleSize = 1;
     if(height>reqHeight||width>reqWidth){
         int halfHeight = height/2;
         int halfWidth = width/2;
         //计算缩放比,是2的指数
         while((halfHeight/inSampleSize)>=reqHeight&&(halfWidth/inSampleSize)>=reqWidth){
               inSampleSize*=2;
         }
     }

     return inSampleSize;
  }

This time it can by way of efficient Load picture:

  mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.mipmap.ic_launcher,100,100);

In addition to BitmapFactorythe decodeResourcemethod, other methods may be similar implementations.

More details, please pay attention to my GitHub: https://github.com/xiangjiana/Android-MS

Guess you like

Origin blog.51cto.com/14541311/2474122