1、图片的质量压缩
图片的质量压缩是指,仅仅压缩图片文件的大小,但当图片加载到内存中时,占用的内存大小并没有太大变化。可以通过质量压缩,加快图片上传的速度。
代码如下:
/**
*将文件压缩后覆盖源文件
*/
public static void compressImage(File file) {
Bitmap bitmap=BitmapFactory.decodeFile(file.getAbsolutePath());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 80;//先压缩到80%
while (baos.toByteArray().length / 1024 > 200) { // 循环判断如果压缩后图片是否大于200kb,大于继续压缩
if (options <= 0) {//有的图片过大,可能当options小于或者等于0时,它的大小还是大于目标大小,于是就会发生异常,异常的原因是options超过规定值。所以此处需要判断一下
break;
}
baos.reset();// 重置baos即清空baos
options -= 10;// 每次都减少10
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
}
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.close();
baos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
通过上述代码,可以将2.5M的图片压缩到200KB左右,并且图片的清晰度差别不大,但是需要注意的是,这改变的只是图片文件的大小,并不能改变加载此图片的内存大小。所以对于此类图片,在加载的时候也是需要注意的,避免OOM异常。需要注意的是,上述代码执行时,还是需要时间的,所以最好放在子线程中执行。
2、缩略图生成
缩略图生成的图片会改变内存占用的大小,所以一般不需要显示全图情况,可以用缩略图去展示,减少程序内存损耗。
代码如下:
/**
* 获取缩略图
* @param imagePath:文件路径
* @param width:缩略图宽度
* @param height:缩略图高度
* @return
*/
public static Bitmap getImageThumbnail(String imagePath, int width, int height) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; //关于inJustDecodeBounds的作用将在下文叙述
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
int h = options.outHeight;//获取图片高度
int w = options.outWidth;//获取图片宽度
int scaleWidth = w / width; //计算宽度缩放比
int scaleHeight = h / height; //计算高度缩放比
int scale = 1;//初始缩放比
if (scaleWidth < scaleHeight) {//选择合适的缩放比
scale = scaleWidth;
} else {
scale = scaleHeight;
}
if (scale <= 0) {//判断缩放比是否符合条件
be = 1;
}
options.inSampleSize = scale;
// 重新读入图片,读取缩放后的bitmap,注意这次要把inJustDecodeBounds 设为 false
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(imagePath, options);
// 利用ThumbnailUtils来创建缩略图,这里要指定要缩放哪个Bitmap对象
bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
return bitmap;
}
通过上述代码加载图片的缩略图,将会有效的避免OOM异常。在这里需要解释下options.inJustDecodeBounds这个属性,当options.inJustDecodeBounds设置为true时,通过BitmapFactory.decodeFile去加载图片,将不会正真地返回bitmap,也就是说此时的bitmap为null。它的作用是将图片的相关信息,例如图片宽高,大小等信息带到options中,方便我们后续计算图片的宽高比。
当我们计算好宽高比后,通过options.inSampleSize来设置缩放比例,然后将options.inJustDecodeBounds的值设置为false,再通过BitmapFactory.decodeFile去加载图片就能获取真正的bitmap对象了。最后通过ThumbnailUtils.extractThumbnail来获取最终的缩略图。需要说明的是,ThumbnailUtils.OPTIONS_RECYCLE_INPUT表示回收创建缩略图时的资源。
或许有的朋友觉得既然已经通过BitmapFactory.decodeFile的方式处理过了,为什么还需要ThumbnailUtils.extractThumbnail来再处理一次呢。首先,仅仅通过之前的处理,最终的缩略图的宽高还是和我们设置的大小有点出入的,所以用ThumbnailUtils再处理一次。可能又会有人说了,为什么不直接使用ThumbnailUtils来生成缩略图呢?因为使用ThumbnailUtils是需要传入bitmap的,试问有没有这样的情况,图片太大,导致在加载图片的时候直接就OOM了,那还怎么使用ThumbnailUtils呢?
本人Android菜鸟一枚,如有错误,欢迎指正,谢谢大家!