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 Bitmap
when 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 ImageView
to display pictures, a lot of time ImageView
and 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 ImageView
there 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 ImageView
is displayed, but also in a reduced memory footprint thereby
avoiding certain extent OOM
, improved Bitmap
performance 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
, decodeStream
and decodeByteArray
, respectively, from the file system,
loading the resource, and the byte array input stream a Bitmap object, which decodeFile,decodeResource
in turn called indirect decodeStream
methods, four methods that ultimately
at the bottom of the Android achieved, corresponding to BitmapFactory
a few native methods of the class.
2. BitmapFactory.Options
Parameters
① inSampleSize
parameters of
the above-mentioned four types of methods support BitmapFactory.Options
parameters, and Bitmap
by a certain sampling rate reduction
release is through the BitmapFactory.Options
parameters achieved, the main use of the inSampleSize
parameters, namely
the sampling rate. By inSampleSize
setting 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, inSampleSize
the value should always be 2 index, such as 1,2,4,8 and so on.
If the incoming external inSampleSize
value 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 inSampleSize
Note 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 ImageView
desired size, so the picture will be stretched and cause blurred.
② inJustDecodeBounds
parameters
we need to get a load of the picture width and height information, and then to the inSampleSize
parameter 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=false
re-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 drawable
directory, or run in different screen densities provided
on the apparatus, it may lead to BitmapFactory
acquired different results , and resource loading mechanism of Android
related
3. Efficient loading Bitmap
process
① will be BitmapFactory.Options
the inJustDecodeBounds
parameter to true and Load picture.
② From the BitmapFactory.Options
taken pictures of the original width and height information, which correspond to outWidth
and outHeight
parameters.
③ According to the regular sampling rate and the required size of View binding target sample rate is calculated inSampleSize
.
④ to BitmapFactory.Options
the inJustDecodeBounds
parameter set to false, then reload the
picture.
Third, Bitmap
efficient 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 BitmapFactory
the decodeResource
method, other methods may be similar implementations.
More details, please pay attention to my GitHub: https://github.com/xiangjiana/Android-MS