一、什么是Bitmap
Bitmap在Android中指一张图,格式不定。BitmapFactory提供了四类方法:decodeFile.decodeResource
decodeStream和decodeByteArray,分别支持从文件,资源,输入流以及字节数组加载出一个bitmap对象,
其中decodeFile和decodeResource间接调用了decodeStream。
二、高效加载的核心原理
怎么高效地加载Bitmap,可以说之加载所需尺寸就行了,一般来说原始图片都比显示出来的图片要大,
越大的图片加载速度、效率就会越低,那么我们在加载之前对图片进行缩放处理,这样使得效率提高,而且
可以在一定程度上避免OOM我们通过BitmapFactory.Options来缩放图片,主要是其中的inSampleSize参数,
即采样率。当inSampleSize为1时,采样后的图片大小为原始大小;当inSampleSize为2时,那么采样后的宽
高均为原图的1/2,而像素数为原图的1/4,内存占用也为原图的1/4,在Goole官方文档中还指出
inSampleSize的取值应该总为2的指数,比如:1,2,4,8...如果不为2的指数那么系统会自动向下取整并选择
一个最接近2的指数来代替。
三、实际开发中的意外情况
另外考虑以下实际情况,假设我们用ImageView来显示图片,当ImageView的大小为100x100像素,而图片
原始大小为200x200,那么只需将采样率inSampleSize设置为2即可,但是如果图片大小为200x300呢?如果采
样率选择2,那么缩放后图片大小为100x150,也可以继续用ImageView,如果采样率为3,那么缩放后图片大小
就会小于ImageView,所期望的大小,那么图片会被自动拉伸而导致模糊
(ImageView底层代码原理,当加载的资源与本身大小不一样时,会自动调用requestLayout(),然后调用
父节点的requestLayout()重新布局,在此过程中会自动对资源进行缩放拉伸处理)
四、过程
获取采样率
1.将BitmapFactory.Options的inJustDecodeBounds参数设置为false,并加载图片(为了测量图片宽高)
2.从BitmapFactory.Options中取出图片的原始宽高信息(存放在options参数中)
3.根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize。
4.将BitmapFactory.Options的inJustDecodeBounds参数设置为false,并重新加载图片
注释:当inJustDecodeBounds为true时,只会解析图片的宽高信息,而不去加载图片
代码如下:
public class MainActivity extends AppCompatActivity {
private ImageView im_1;
private ImageView im_2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
im_1 = (ImageView) findViewById(R.id.im_1);
im_2= (ImageView) findViewById(R.id.im_2);
im_1.setBackgroundResource(R.drawable.tiantang);
im_2.setImageBitmap(decodeSampledBitmapFromResources(getResources(),R.drawable.tiantang,100,100));
}
private Bitmap decodeSampledBitmapFromResources(Resources res,int resId,int reqWidth,int reqHeight){
//1.找到BitmapFactory实例
BitmapFactory.Options options = new BitmapFactory.Options();
//2.设置inJustDecodeBounds参数为True
options.inJustDecodeBounds = true;
//3.得到BitmapFactory加载进来的图片
BitmapFactory.decodeResource(res, resId, options);
//4.计算缩放比
options.inSampleSize =calculateInSampleSize(options,reqWidth,reqHeight);
options.inJustDecodeBounds =false;
return BitmapFactory.decodeResource(res,resId,options);
}
private int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
int height = options.outHeight;
int width = options.outWidth;
int inSampleSize =1;
//当图片宽高其中一个大于要求宽高
if(height>reqHeight||width >reqWidth){
int halfHeight = height/2;
int halfWidth = width/2;
//循环直到得到合适的采样率
while((halfHeight/inSampleSize)>=reqHeight && (halfWidth/inSampleSize)>=reqWidth){
inSampleSize *=2;
}
}
return inSampleSize;
}
}