大多数情况下,我们的应用加载的图片的实际大小都比需要显示的尺寸要大,比如手机相机拍摄的照片的分辨率要比手机屏幕的分辨率高很多。
理想情况下我们只需要加载一张低分辨率的图片显示给用户,同时图片的宽高应该根据对应的显示UI控件的大小来匹配,加载超过要求宽高的图片资源没有显而易见的好处,同时会占用很高的内存资源,在快速滑动时容易产生的效率问题。
Android的BitmapFactory提供了一系列用于创建位图的方法。用于从不同的资源类型中来创建位图。可以根据图片的数据源选择合适的方法。其中每个方法都可以根据BitmapFactory.Options来设置一些加载参数。
通过设置BitmapFactory.Options实例的inJustDecodeBounds属性为true从而实现在不分配内存的情况下返回一个空的bitmap,但是可以通过这种方式回去图片资源的尺寸和类型。实现如下:
BitmapFactory.Options options =newBitmapFactory.Options();
options.inJustDecodeBounds =true;
BitmapFactory.decodeResource(getResources(),R.id.myimage, options);
int imageHeight =options.outHeight;
int imageWidth =options.outWidth;
String imageType = options.outMimeType;
这样我们就可以判断图片资源的尺寸是否需要压缩。
BitmapFactory.Options有一个inSampleSize属性,可以使用该属性来对图片资源进行压缩操作,例如对于一个1920*1080分辨率的图片,在设置inSampleSize为4后,可以产生一个大小约为480*270大小的图片。那么如何来确定inSampleSize属性的值呢,实现如下:
public static int calculateInSampleSize(BitmapFactory.Options 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;
// 计算图片宽高缩小为要求大小时的最大inSampleSize值
while
((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *=
2;
}
}
return
inSampleSize;
}
在确定了inSampleSize的值之后,我们就可以来进行bitmap的构建操作了。这里需要注意的是需要先把inJustDecodeBounds设置为true先获到的BitmapFactory.Operations实例的值,然后再将inJustDecodeBounds设置为false。之后即可进行相关的操作,实现如下:
public static Bitmap decodeBitmapFromResourceByReqHeiReqWid(Resources res, int resId,int reqWidth, int reqHeight){
// 先将inJustDecodeBounds设置为true获取图片宽高等信息
final
BitmapFactory.Options options =
newBitmapFactory.Options();
options.inJustDecodeBounds =
true;
BitmapFactory.decodeResource(res, resId, options);
// 根据上面的方法计算 inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 构建bitmap并返回
options.inJustDecodeBounds =
false;
return
BitmapFactory.decodeResource(res, resId, options);
}
最后,我们就可以使用上面的方法来读取一个小尺寸的图片用于显示了如:
imageView.setImageBitmap(
decodeBitmapFromResourceByReqHeiReqWid(res,resId,reqWidth,reqHeight));