加载图片尺寸和类型针对不同的图片数据来源,BitmapFactory提供了不同的解码方法(decodeResource()、decodeFile()...),这些方法在构造图片的时候会申请相应的内存空间,所以它们经常抛出内存溢出的异常。这些方法都允许传入一个BitmapFactory.Options类型的参数来获取将要构建的图片的属性。如果将inJustDecodeBounds的值设置成true,这些方法将不会真正的创建图片,也就不会占用内存,它们的返回值将会是空。但是它们会读取图片资源的属性,我们就可以从BitmapFactory.Options中获取到图片的尺寸和类型。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
解码图片之前先检查图片的大小可以有效的避免内存溢出,除非你很确定你要加载的图片不会导致内存溢出。
加载缩小比例的图片到内存中现在图片的尺寸已经获取了,接下来就是判断是将图片全尺寸加载到内存还是加载一个缩小版。判断的标准有以下几条:
全尺寸的图片需要占用多大内存空间;
应用能够提供给这张图片的内存空间的大小;
展示这张图片的imageview或其他UI组件的大小;
设备的屏幕大小和密度。
例如,填充100x100缩略图imageview时就没有必要将1024x768的图片全尺寸的加载到内存中。这时就要设置BitmapFactory.Options中的inSampleSize属性来告诉解码器来加载一个缩小比例的图片到内存中。如果以inSampleSize=4的设置来解码这张1024x768的图片,将会得到一张256x196的图片,加载这张图片使用的内存会从3M减少到196K 。inSampleSize的值是根据缩放比例计算出来的一个2的n次幂的数。下面是计算inSampleSize常用的方法。
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
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;
// 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 ((halfHeight / inSampleSize) >= reqHeight&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
加载缩小比例图片大致有三个步骤:inJustDecodeBounds设置为true获取原始图片尺寸 --> 根据使用场景计算缩放比例inSampleSize --> inJustDecodeBounds设置为false,传递inSampleSize给解码器创建缩小比例的图片。示例代码如下:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
有了上面的方法我们就可以很轻松的为大小为100x100缩略图imageview加载图片了。
mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));