Android高效压缩图片不失真的方法总结

前言

之前有个项目我负责聊天模块,做到图片消息那一块时,因为需要先上传到服务器然后取得返回的图片网络地址,考虑到无论是从相机拍摄还是从相册上传的图片,都有可能由于过大从而导致发送消息耗时过长以及损耗用户手机流量,所以需要在上传前对图片进行有效的压缩,网上提供的做法有许多种,经过反复试验,我总结出了以下影响图片大小的几个因素以及对应的属性和方法:
1.图片的尺寸,对应BitmapFactory.Option的inSampleSize值。
inSampleSize值表示缩略图大小为原图大小的几分之一。例如,inSampleSize==4时则缩略图的宽和高都为原图的1/4,相应的图片大小就为原始大小的1/16,如果inSampleSize值<=1时则取1。需要注意的是,inSampleSize值只能是2的整数次幂,如果不是的话则会向下取得最大的2的整数次幂。
2.图片的格式,对应Bitmap的compress(Bitmap.CompressFormat format, int quality, OutputStream stream)方法中第一个参数。
CompressFormat类是个枚举,有三个取值:JPEG、PNG和WEBP。其中,PNG是无损格式(忽略质量设置),会导致方法中的第二个参数压缩质量失效,JPEG不解释,而WEBP格式是Google新推出的,据官方资料称“在质量相同的情况下,WEBP格式图像的体积要比JPEG格式图像小40%。”
3.图片的质量,对应Bitmap的compress(Bitmap.CompressFormat format, int quality, OutputStream stream)方法中第二个参数,取值范围为0-100, 0表示压缩为最小质量,100表示压缩为最大质量(即保持原图质量)。


实现

1.首先,为了获取图片的实际宽高,需设置BitmapFactory.Options的inJustDecodeBounds值为true,设为true表示只是解码图片的边距,而没有实际返回一个Bitmap对象,从而不会因为解码图片过程中占用太多内存而频繁发生OOM,操作完成后需将该值重新设为false。

            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inJustDecodeBounds = true;
            Bitmap bmp = BitmapFactory.decodeFile(sourceImgPath, opts);
            opts.inJustDecodeBounds = false;

2.根据自身需要设定缩放比。以目前主流的分辨率之一400*800为基础,根据宽或高其中一个数据进行等比例缩放,然后将BitmapFactory.Option的inSampleSize值设为计算出的缩放比例即可。

            int w = opts.outWidth;
            int h = opts.outHeight;
            float standardW = 480f;
            float standardH = 800f;

            int zoomRatio = 1;
            if (w > h && w > standardW) {
                zoomRatio = (int) (w / standardW);
            } else if (w < h && h > standardH) {
                zoomRatio = (int) (h / standardH);
            }
            if (zoomRatio <= 0)
                zoomRatio = 1;
            opts.inSampleSize = zoomRatio;

3.重新读入图片,由于前面已经把BitmapFactory.Options的inJustDecodeBounds值重新设为false了,所以此次会返回一个实际的Bitmap对象。

            bmp = BitmapFactory.decodeFile(sourceImgPath, opts);

4.根据自身需要设定压缩格式和压缩质量,这里提供了几种不同格式与质量下的压缩后图片大小对比:

            bmp.compress(Bitmap.CompressFormat.JPEG, 10, fos);
Android高效压缩图片不失真的方法总结_第1张图片

Android高效压缩图片不失真的方法总结_第2张图片

下面是原图:


由上面的对比可以看出:
1.PNG格式的确是忽略质量设置的,不同压缩质量下图片大小不变,所以PNG格式的图片只能通过改变图片尺寸进行压缩。
2.压缩质量为50时,三种格式下的图片用肉眼是察看不出什么区别的,即保证了图片不失真。
3.压缩质量为10时,JPEG格式和WEBP格式的图片已经有了较为明显的失真,但JPEG格式的图片失真更为严重。
4.改变图片尺寸对压缩图片效果最佳


参考

http://104zz.iteye.com/blog/1694762


源码

http://download.csdn.net/detail/alfred_c/9410079


你可能感兴趣的:(Android)