android图片压缩的三种方式

为了避免oom的出现,几乎每个应用都会对大图进行压缩,我现在手头做的产品就有很多地方用到,以前封装工具类的时候,都是在网上找东找西,然后拼拼凑凑,有效果就行了,一直用的迷迷糊糊,这几天工作比较闲,正好系统的总结梳理一下图片压缩方式:

图片压缩现在常见的有三种方式:

1、等比压缩,等比压缩是保持原图长宽比例的压缩,只是图片变小,展示的还是原图的所有内容(区别于第二种通过Matrix压缩,可以选取图片的一部分,类似于上传头像时,让你在图上选一块zoom的形式)。等比压缩用的的主要是BitmapFactory.Options,通过options缩放比例的设置,来生成缩略图:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * @param path 图片路径 
  3.      * @param targetSize 缩放后期待的长边(图片长和宽大的那一个边)的长度 
  4.      * @param targetW 期待的缩放后宽度 
  5.      * @param targetH 期待的缩放后高度 
  6.      * @return 
  7.      */  
  8.     public static Bitmap equalRatioScale(String path,int targetW,int targetH){  
  9.         // 获取option  
  10.         BitmapFactory.Options options = new BitmapFactory.Options();  
  11.         // inJustDecodeBounds设置为true,这样使用该option decode出来的Bitmap是null,  
  12.         // 只是把长宽存放到option中  
  13.         options.inJustDecodeBounds = true;  
  14.         // 此时bitmap为null  
  15.         Bitmap bitmap = BitmapFactory.decodeFile(path, options);  
  16.         int inSampleSize = 1// 1是不缩放  
  17.         // 计算宽高缩放比例  
  18.         int inSampleSizeW = options.outWidth / targetW;  
  19.         int inSampleSizeH = options.outHeight / targetH;  
  20.         // 最终取大的那个为缩放比例,这样才能适配,例如宽缩放3倍才能适配屏幕,而  
  21.         // 高不缩放就可以,那样的话如果按高缩放,宽在屏幕内就显示不下了  
  22.         if (inSampleSizeW > inSampleSizeH) {   
  23.             inSampleSize = inSampleSizeW;  
  24.         }else {  
  25.             inSampleSize = inSampleSizeH;  
  26.         }  
  27.         // 设置缩放比例  
  28.         options.inSampleSize = inSampleSize;  
  29.         // 一定要记得将inJustDecodeBounds设为false,否则Bitmap为null  
  30.         options.inJustDecodeBounds = false;  
  31.         bitmap = BitmapFactory.decodeFile(path, options);  
  32.         return bitmap;  
  33.     }  

2、通过Matrix进行更加灵活的缩放:这种方式主要是通过构建缩放矩阵和Bitmap.createBitmap方法来实现灵活缩放,宽和高缩放的比例可以不一致,而且通过Bitmap.createBitmap方法创建出来的是新的位图,这个位图可以是选取原图的一部分,而不是对原图进行整体缩放!类似于上传头像时,让你在原图上扣下来一块的效果,控制非常灵活。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.      * @param path 原图路径 
  3.      * @param offsetX 截取开始点在X轴偏移量 
  4.      * @param offsetY 截取开始点在Y轴偏移量 
  5.      * @param targetW 截取多宽(像素) 
  6.      * @param targetH 截取多高(像素) 
  7.      * @return 
  8.      */  
  9.     public static Bitmap matrixScale(String path,int offsetX,int offsetY,int targetW,int targetH){  
  10.         // 构建原始位图  
  11.         Bitmap bitmap = BitmapFactory.decodeFile(path);  
  12.         // 获取原始宽高  
  13.         int width = bitmap.getWidth();  
  14.         int height = bitmap.getHeight();  
  15.         // 计算宽高缩放比例,targetW,targetH即期待缩放完成后位图的宽高  
  16.         float scaleW = (float)targetW / width;  
  17.         float scaleH = (float)targetH / height;  
  18.         // 将缩放比例放进矩阵  
  19.         Matrix matrix = new Matrix();  
  20.         matrix.postScale(scaleW, scaleH);  
  21.         // 这个方法作用非常多,详细解释一下各个参数的意义!  
  22.         // bitmap:原始位图  
  23.         // 第二到第五个参数,即截取原图哪一部分构建新位图,  
  24.         // offsetX和offsetY代表在X轴和Y轴上的像素偏移量,即从哪个位置开始截取  
  25.         // width和height代表截取多少个像素,但是要注意,offsetX+width应该小于等于原图的宽度  
  26.         // offsetY+height小于等于原图高度,要不然会报错,因为截到原图外面去了  
  27.         // 像下面这样填写,就代表截取整个原图,  
  28.         // Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);  
  29.         // 如果填写100,100,200,200,就代表  
  30.         // 从原图左上角往右和下各偏移100像素,然后往后和往下各截取200构建新位图  
  31.         // matrix:缩放矩阵  
  32.         // 最后一个参数表示如果矩阵里面还存放了过滤条件,是否按条件过滤(如果matrix里面只放了平移数据),最后一个参数设置成什么都不会生效  
  33.         bitmap = Bitmap.createBitmap(bitmap, offsetX, offsetY, width, height, matrix, false);  
  34.         return bitmap;  
  35.     }  

3、无损压缩,无损压缩是说图片大小和清晰度看上去和原图没有什么差别,但是确实size缩小了,这里缩小的原理是牺牲了分辨率等其他直观看不到的东西,看起来和原图一样,但是一放大就立马失真了,不会和原图一样放大很多才会逐渐变得不清晰。无损压缩后的图片像素并不会减少,而Bitmap占用内存的定义就是像素点占的内存,所以以Bitmap的方式加载到内存中时,和压缩前占用的内存是同样大的,原来会oom的图片,质量压缩后同样会oom;但是,质量压缩后将流输出到文件中,文件的size会大幅度减小,所以质量压缩特别适合在Android端进行图片上传的时候进行图片压缩,既能保持上传后的清晰度,又能减小size。另外质量压缩不是可以无限缩小的,降低到一定程度,就算把quality设置的再小,size也不会再降低了。另外这种方式最好返回保存压缩后的图片保存的文件路径,而不要直接返回Bitmap,示例就懒得改了。

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <pre name="code" class="java">/** 
  2.      * @param path 图片路径 
  3.      * @param quality 质量 0-100,100表示原图 
  4.      * @return 
  5.      */  
  6.     public static Bitmap losslessScale(String path,int quality){  
  7.         Bitmap bitmap = BitmapFactory.decodeFile(path);  
  8.         ByteArrayOutputStream baos = new ByteArrayOutputStream();    
  9.         bitmap.compress(CompressFormat.JPEG, quality, baos);  
  10.         Log.e("哈哈","原始大小:" + baos.toByteArray().length);  
  11.         // 因为质量压缩不是可以无限缩小的,所以一张高质量的图片,再怎么压缩,  
  12.         // 最终size可能还是大于你指定的size,造成异常  
  13.         // 所以不建议循环压缩,而是指定quality,进行一次压缩就可以了  
  14. //        while (baos.toByteArray().length / 1024 > maxSize) {    
  15. //            quality -= 10;    
  16. //            baos.reset();    
  17. //            bitmap.compress(CompressFormat.JPEG, quality, baos);    
  18. //            Log.e("哈哈","过程中大小为:"    
  19. //                    + baos.toByteArray().length);  
  20. //        }    
  21.         bitmap.compress(CompressFormat.JPEG, quality, baos);    
  22.         Log.e("哈哈","最终大小" + baos.toByteArray().length);  
  23.         Bitmap compressedBitmap = BitmapFactory.decodeByteArray(    
  24.                 baos.toByteArray(), 0, baos.toByteArray().length);    
  25.         return compressedBitmap;    
  26.     }  


 

一张图片处理过程,建议先进行等比压缩或者Matrix压缩后,再进行质量压缩,这样组合使用,不管是生成缩略图还是图片上传,效果都不错

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值