我用的图片主要分为3种 1、质量压缩 ,2、尺寸压缩,3、Luban压缩(鲁班)
一、质量压缩
质量压缩的特点是: File形式的图片确实被压缩了, 但是当你重新读取压缩后的file为 Bitmap是,它占用的内存并没有改变
质量压缩主要借助Bitmap中的compress方法实现:
public boolean compress (Bitmap.CompressFormat format, int quality, OutputStream stream)
这个方法用来将特定格式的压缩图片写入输出流(OutputStream)中,当然例如输出流与文件联系在一起,压缩后的图片也就是一个文件。如果压缩成功则返回true,其中有三个参数:
- format是压缩后的图片的格式,可取值:Bitmap.CompressFormat .JPEG、~.PNG、~.WEBP。
- quality的取值范围为[0,100],值越小,经过压缩后图片失真越严重,当然图片文件也会越小。(PNG格式的图片会忽略这个值的设定)
- stream指定压缩的图片输出的地方,比如某文件。
下面是质量压缩的代码:
- public static void compressBmpToFile(Bitmap bmp,File file){
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- int options = 80;//个人喜欢从80开始,
- bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
- while (baos.toByteArray().length / 1024 > 100) {
- baos.reset();
- options -= 10;
- bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
- }
- try {
- FileOutputStream fos = new FileOutputStream(file);
- fos.write(baos.toByteArray());
- fos.flush();
- fos.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
二、尺寸压缩
特点: 通过设置采样率, 减少图片的像素, 达到对内存中的Bitmap进行压缩
我们主要通过BitmapFactory中的decodeFile方法对图片进行尺寸压缩:
public static Bitmap decodeFile (String pathName, BitmapFactory.Options opts)
其中有两个参数:
- pathName是图片文件的路径。
- opts 就是所谓的采样率,它里边有很多属性可以设置,我们通过设置属性来达到根据自己的需要,压缩出指定的图片。其中比较常用的属性有:
boolean inJustDecodeBounds —— 如果设置为true,则只读取bitmap的宽高,而忽略内容。
int inSampleSize—— 如果>1,调用decodeFile方法后,就会得到一个更小的bitmap对象(已压缩)。比如设置为2,那么新Bitmap的宽高都会是原Bitmap宽高的1/2,总体大小自然就是原来的1/4了,以此类推。
boolean inPurgeable—— 如果设置为true,压缩后的图片像素占的内存将会在系统清理内存的时候被回收掉,当像素的信息再次被用到时将会自动重新decode该像素(比如getPixels()时)。(慎用!重复decode可以会造成UI的卡顿,API level 21 已弃用)
boolean inInputShareable—— 与inPurgeable配合使用,如果inPurgeable设置成false,自动忽略此值,如果inPurgeable为true,此值决定是否该bitmap能分享引用给输入数据(inputstream,array等),或者必须进行深拷贝。API level 21 已弃用。(这是译文,不太理解!!!)
下面是一段实现的代码
-
private Bitmap sizeCompres(String path, int rqsW, int rqsH) {
-
// 用option设置返回的bitmap对象的一些属性参数
-
final BitmapFactory.Options options = new BitmapFactory.Options();
-
options.inJustDecodeBounds = true;// 设置仅读取Bitmap的宽高而不读取内容
-
BitmapFactory.decodeFile(path, options);// 获取到图片的宽高,放在option里边
-
final int height = options.outHeight;//图片的高度放在option里的outHeight属性中
-
final int width = options.outWidth;
-
int inSampleSize = 1;
-
if (rqsW == 0 || rqsH == 0) {
-
options.inSampleSize = 1;
-
} else if (height > rqsH || width > rqsW) {
-
final int heightRatio = Math.round((float) height / (float) rqsH);
-
final int widthRatio = Math.round((float) width / (float) rqsW);
-
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
-
options.inSampleSize = inSampleSize;
-
}
-
return BitmapFactory.decodeFile(path, options);// 主要通过option里的inSampleSize对原图片进行按比例压缩
-
}
三、Luban压缩
这里介绍下一个第三方开源库——Luabn(最接近微信朋友圈压缩图片算法)
2.使用Luban压缩图片效果
上面两图中的上部分图片是原图,下面部分是经过Luban压缩过后的图片
效果:
第一张原图4.55m 尺寸3456x4608。 压缩过后53k 尺寸1152x1536
第二张原图1.16m 尺寸1080x1920。 压缩过后150k 尺寸360x640
我们可以发现压缩后的图片在不放大的情况下,图片效果和原图一致,Luban的处理效果特别好。
如何使用Luban压缩图片
1.在项目中的build.gradle添加依赖(需要用到RxJava1.0)
2.在代码中使用Luban压缩方法
1)Listerner方式。传入图片File,调用设置压缩监听setCompressListerner方法,处理压缩结果。
2)Rxjava方式,传入图片File,调用asObservable方法返回一个Observable观察者对象,使用RxJava方式来处理压缩结果。
3.Luban源码分析
源码中最主要的方法就是thirdCompress(File file),即如何计算得出理想的压缩后宽高,以及图片大小。
Luban存在的不足
1.不能很好的支持多图片压缩。(出现问题:多图压缩出现OOM)
2.项目使用中必须添加RxJava依赖。(已在测试项目中剔除掉RxJava依赖 「链接」)