通过采样率压缩图片的步骤:
- 将BitmapFactory.Options的inJustDecodeBounds参数设置为true并加载图片
- 从BitmapFactory.Options中取出图片的原始宽和高 ,分别对应outWidth和outHeight
- 根据采样率的就着并结合目标View的所需大小计算出采样率inSampleSize
- 将BitmapFactory.Options的inJustDecodeBounds参数设置为false,然后重新加载图片
BTW: 说一下BitmapFactory.Options的inJustDecodeBounds属性,当参数设置为true时,BitmapFactory只会解析图片的原始宽和高,并不会将图片加载到内存中。
// 如果图片不存在 则添加到任务队列中
addTask(new Runnable() {
@Override
public void run() {
// 加载图片 TODO
// 1.获取图片需要显示的宽和搞
ImageSize imageSize = getImageViewSize(imageView);
// 利用Options压缩图片
Bitmap bm = decodeSampledBitmapFromPath(path, imageSize.width, imageSize.height);
// 添加到LruCache中
addBitmapToLruCache(path, bm);
// 发送消息,通知UIHandler更新图片
ImageBeanHoler holder = new ImageBeanHoler();
holder.bitmap = getBitmapFromLruCache(path);
holder.imageView = imageView;
holder.path = path;
Message message = Message.obtain();
message.obj = holder;
mUIHandler.sendMessage(message);
// 执行完之后,释放一个信号量,通知mPoolThread可以从任务队列中获取下一个任务了去执行了。
mPoolThreadSemaphore.release();
}
});
/**
* 根据计算的inSampleSize得到压缩的图片
*
* @param path
* @param reqWidth
* @param reqHeight
* @return
*/
private Bitmap decodeSampledBitmapFromPath(String path, int reqWidth, int reqHeight) {
// 第一次解析将inJustDecodeBounds设置为true,不将图片加载到内存,获取图片的大小
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// 计算inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 使用获取到的inSampleSize再此获取图片,加载到内存中
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
return bitmap;
}
/**
* 这个方法用户可以自己设置适合项目的图片比例
*
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// 源图片的宽度
int width = options.outWidth;
int height = options.outHeight;
int inSampleSize = 1;
if (width > reqWidth && height > reqHeight) // ||也是可以的,看实际情况
{
// 计算出实际宽度和目标宽度的比率
int widthRatio = Math.round((float) width / (float) reqWidth);
int heightRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = Math.max(widthRatio, heightRatio); // 为了节省内存,取了大值。如果有变形,取小值试试。
}
return inSampleSize;
}