Bitmap的高效加载分为以下4步:
- 将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片。
- 从BitmapFactory.Options中取出图片的原始宽高信息,对应于outWidth和outHeight参数。
- 根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize。
- 将BitmapFactory.Options的inJustDecodeBounds参数设为false,然后重新加载图片。
有几个值得注意的地方:
- BitmapFactory.Options的inJustDecodeBounds参数。当inJustDecodeBounds为true时,BitmapFactory只会解析图片的原始宽高信息(得到原始宽高用于后面计算采样率),并不会真正地去加载图片,所以这个操作是轻量级的,并不会因为图片过大而产生OOM。
- 采样率。采样率即inSampleSize参数,当采样率小于1时,与当采样率为1的效果相同;当采样率为1时,采样后打图片即为原始图片的大小,当采样率为2时,采样后的图片其宽高均为原始图片大小的1/2,像素图为原图的1/4,所占内存也为原始图片的1/4;另外,inSampleSize的取值应总是为2的指数,如1,2,4,8,16等等,如果不为2的指数,那么系统会自动向下取整选择一个最接近2的指数的数来代替,比如如果inSampleSize设置为3,那么系统会自动将inSampleSize变成2,但并不是所有Android版本都成立,实际开发中需灵活应对。
- 采样率的实际应用情况。如果ImageView的大小为100×100像素,而图片的原始大小为240×300,这个时候采样率应该为2,即采样后的大小为120×150,而如果把采样率设为3,那么缩放后的图片大小就为80×100,小于ImageView所期望的大小,这时候图片就会被拉伸而导致模糊。
代码:
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);
//inJustDecodeBounds 参数为true,轻量化加载图片
options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);
//计算采样率
options.inJustDecodeBounds =false;
return BitmapFactory.decodeResource(res,resId,options);
//inJustDecodeBounds 参数为false,重新加载图片,此时图片加载到ImageView里面
}
//下面是计算采样率的方法
//reqWidth和reqHeight对应的是ImageView的宽高
public static int caculateInSampleSize(BitmapFactory.Options,int reqWidth,int reqHeight){
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if(height > reqHeight || width > reqWidth){
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while(((halfHeight / inSampleSize) >= reqHeight) && ((halfWidth / inSampleSize) >=reqWidth)){
inSampleSize *= 2;
}
}
return inSampleSize;
}