Bitmap在Android中指的是一张图片,可以是png格式也可以是jpg等其他常用的图片格式.
如何加载bitmap?
BitmapFactory类提供了四个static方法: decodeFile, decodeResource, decodeStream和decodeByteArray.
Bitmap icon = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.frequent_default);
高效加载bitmap的核心思想
就是通过BitmapFactory.Options类的对象, 设置合理的inSampleSize属性值, 然后把option对象传给刚提到的加载bitmap的四个static方法, 它们都支持BitmapFactory.Options这个参数.
public static Bitmap decodeResource(Resources res, int id, Options opts)
inSampleSize: 采样率
一张10241024像素的图片,假定采用ARGB8888格式存储,占内存大小为102410244, 即4MB. 如果inSampleSize为2,那么采样后的图片宽高为原来的1/2,即512512像素, 占内存大小为5125124, 即1MB.
注意两点:
- 设置inSampleSize值小于1时,其作用相当于1, 即无缩放效果.
- 官方文档建议inSampleSize值为2的指数, 即1,2,4,8,16,等等.
设置合理的inSampleSize值
考虑以下的实际情况, 假设ImageView的大小为100100像素,而图片的原始尺寸为200200,那么设置inSampleSize为2即可,如果图片原始尺寸为200300,设置inSampleSize为2,缩小后的图片尺寸是100150,设给这个ImageView也没问题, 但如果设置inSampleSize为4, 缩小后的尺寸为50*75,达不到ImageView所期望的大小, 这时候这个图片就会被拉伸从而导致模糊, 这显然不是我们所期望看到的.
获取合理的采样率也简单, 可通过如下的流程:
- 将BitmapFactory.Options的inJustDecodeBounds参数设为true并加载图片.
- 从BitmapFactory.Options中取出图片的原始宽高,它们对应于outWidth和outHeight参数.
- 结合目标View所需大小,计算出inSampleSize的值.
- 将BitmapFactory.Options的inJustDecodeBounds参数设为false,然后从新加载图片.
这里说明一下inJustDecodeBounds参数的含义,当此参数为true时,BitmapFactory只会解析图片的原始宽高信息, 并不会去真正的加载图片,所以这个操作是轻量级的.
对上面的流程用代码实现下:
public static Bitmap decodeResourceEx(Resources res, int resId, int reqWidth, reqHeight) {
//first, decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, id, options);
int originWidth = options.outWidth;
int originHeight = options.outHeight;
//calculate inSampleSize
options.inSampleSize = calculateInSampleSize(originWidth, originHeight, reqWidth, reqHeight);
//Decode bitmap with inSampleSize
options.inJustDecodeBounds = false;
return BitmapFacotry.decodeResource(res, resId, options);
}
private int calculateInSampleSize(originWidth, originHeight, reqWidth, reqHeight) {
int inSampleSize = 1;
if(originWidth>reqWidth || originHeight>reqHeight) {
final int halfWidth = originWidth / 2;
final int halfHeight = originHeight / 2;
//calculate the largest inSampleSize value that is a power of 2 and keeps both height and width larger than the requested height and width.
while(((halfWidth/inSampleSize) >= reqWidth) &&((halfHeight/inSampleSize) >= reqHeight)) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
比如ImageView所期望的图片大小是100*100像素,这个时候就可以通过如下方式高效地加载并显示图片:
mImageView.setImageBitmap(decodeResourceEx(getResources(), R.id.myImage, 100, 100));