您的位置:首页 > 其它

Bitmap处理 之二高效处理大图片

2015-09-07 09:44 260 查看
图片有各种各样的尺寸大小,许多情况下都会比需要的要大。比如系统图册显示的手机拍照的照片比你的设备的屏幕密度要高。

由于使用内存有限,最好是在内存中加载一个低分辨率版本。这个分辨率版本应该匹配显示它的UI组件的大小。一个高分辨率的位图没有啥好处,但仍然占用宝贵的内存控件而且带来额外的性能开销。

这篇文章将说如何加载一个更小的图片样本在内存中。

读取Bitmap尺寸和类型

BitmapFactory类提供了几个解析方法,能从几种资源创建Bitmap。基于你Image资源选出最恰当的方法。这些方法会为创建Bitmap分配内存,因此可能会造成OutOfMemory异常。每种解码方法都可以让你通过BitmapFactory.Options设置标签。设置inJustDecodeBounds 为true,解码的时候会避免内存的分配,返回的bitmap对象为空,但是却可以得到 outWidth, outHeight 和outMimeType。这个技术可以是你在生成Bitmap之前获得到图片的尺寸和类型。

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;


为了避免 java.lang.OutOfMemory 异常,在解析前先核对Bitmap的尺寸,除非你有绝对的把握你的图片不会造成内存溢出。

加载一个按比例缩小版本到内存中

现在知道了图片的尺寸,就能知道到底是原图加载到内存中还是加载一个样品。下面几点可以考虑:

估算加载完整图片使用的内存大小。

加载了完整图片,给应用其他的内存需求大小

目标Imageview尺寸或者加载图片的UI组建大小

当前设备屏幕尺寸或者大小

告诉解码器对Image进行采样,加载一个较小版本图片到内存中,设置BitmapFactory.Options 对象inSampleSize为true。比如一个2048*1536密度的图片,inSampleSize为4生成的样品图就是512*384。加载这个样品需要内存0.75MB,而不是原来的12MB。下面提供了方法计算样本大小。

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;

//计算最大的压缩比例值都是2的幂次方,而且宽和高大于被要求
//的宽和高。
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}

return inSampleSize;
}


用下面地方法,第一步设置inJustDecodeBounds = true,然后通过新的inSampleSize解码,最后设置inJustDecodeBounds = false。

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {

// 第一步inJustDecodeBounds=true 检查尺寸大小
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);

// 计算样本尺寸
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// 进行采样
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}


这个方法就可以把任意尺寸图显示成100*100的缩略图

mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: