图片压缩
申明:低级码农问题解决中的参考和解决后的小结,仅用于个人记录,能力有限,可能有些错误,缺陷不自知,欢迎在评论中指正,谢谢!
参考:
质量压缩方法:https://www.jianshu.com/p/3ac26611bc0d
图片有损压缩与无损压缩对比:https://zhidao.baidu.com/question/214587137.html
图片压缩的目的,是为了减小图片体积,即磁盘占用空间。包括一下几种。
1/质量压缩
质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度,来达到压缩图片的目的,图片的长,宽像素都不会改变,那么bitmap所占内存大小是不会变的。
质量压缩有个关键参数:quality,可以调节你压缩的比例,要注意一点就是,质量压缩对png格式这种图片没有作用,因为png是无损压缩。quality与压缩后的文件大小不是线性关系。另外有个奇怪现象是,手机拍摄的jpg图片,经过质量100的压缩后,图片体积反而略有增加,我理解的是,相机的压缩算法比java原生压缩算法更优,所以压缩后的体积更小。
质量压缩的核心方法在android.graphics.Bitmap中,如下
/** * @param format 压缩格式,包含JPEG,PNG,WEBP * @param quality 压缩比例,低于80会导致图片质量肉眼可见的变差,太高又会导致体积减小不明显 * @param stream * @return */ abstract boolean compress(Bitmap.CompressFormat format, int quality, OutputStream stream);
质量压缩方法如下:
1 private void compress(String inputPath, String outputPath) { 2 Bitmap originBitmap = BitmapFactory.decodeFile(inputPath); 3 try { 4 FileOutputStream fos = new FileOutputStream(new File(outputPath)); 5 BufferedOutputStream bos = new BufferedOutputStream(fos); 6 originBitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); 7 bos.close(); 8 } catch (IOException e) { 9 } 10 }
2/采样率压缩
是将图片读取到内存时,降低采样率。关键参数是BitmapFactory.Options.inSampleSize。当isSampleSize=2时,即x,y方向,分别每2个点取一个点,图片写入内存大小占原理的1/4。。当isSampleSize=3时,即x,y方向,分别每3个点取一个点,图片写入内存大小占原理的1/9。
采样率压缩是减小图片写入内存时占用的内存大小,实际一般通过与质量压缩配合使用,来进一步压缩图片体积。经过采样率压缩后的图片,宽高都会减小(只有原来的isSampleSize分之一),压缩后的图片在写入内存,占用内存空间也会减小。
1 BitmapFactory.Options options = new BitmapFactory.Options(); 2 options.inSampleSize = inSampleSize; 3 Bitmap originBitmap = BitmapFactory.decodeFile(inputPath, options); 4 try { 5 FileOutputStream fos = new FileOutputStream(new File(outputPath)); 6 BufferedOutputStream bos = new BufferedOutputStream(fos); 7 originBitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); 8 } catch (IOException e) { 9 10 }
3/通过Matrix压缩
Matrix压缩的原理是将图片的bitmap读入内存,然后通过matrix缩放比来创建一个新的bitmap。Matrix压缩的处理结果与采样率压缩类似,都可以改变压缩后的图片的宽高,体积。但他们的实现过程有很大的差异。采样率压缩是文件写入内存过程中,只读取部分采样;matrix是先写入一个完整的bitmap,再对这个bitmap变换生成一个新的bitmap。
Matrix的优势是可以设置任何比例的压缩,可以不用保持长宽比来自由压缩。甚至可以通过裁剪来压缩,这种情况我们不讨论。Matrix的劣势是需要将图片的bitmap先读入内存,可能导致内存溢出,不像采样率那样,可以通过参数预读。
1 Bitmap originBitmap = BitmapFactory.decodeFile(inputPath); 2 Matrix matrix = new Matrix(); 3 matrix.setScale(scale, scale); 4 originBitmap = Bitmap.createBitmap(originBitmap, 0, 0, originBitmap.getWidth(), originBitmap.getHeight(), matrix, true); 5 try { 6 FileOutputStream fos = new FileOutputStream(new File(outputPath)); 7 BufferedOutputStream bos = new BufferedOutputStream(fos); 8 originBitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); 9 } catch (IOException e) { 10 11 }
4/编码格式压缩
这种方式是减小图片占用的内存空间。Android将图片写入内存,默认编码格式是ARGB8888,一像素将用4个字节。如果采用其他编码格式,如RGB565,一像素只占用2个字节,可以减小内存占用空间。
有个奇怪的现象是,先通过编码格式压缩,再质量压缩生成的图片文件,比不先经过编码格式压缩,直接质量压缩生成的图片文件生成的文件要大。原因不明。
1 BitmapFactory.Options options = new BitmapFactory.Options(); 2 options.inPreferredConfig = Bitmap.Config.RGB_565; 3 Bitmap originBitmap = BitmapFactory.decodeFile(inputPath, options); 4 try { 5 FileOutputStream fos = new FileOutputStream(new File(outputPath)); 6 BufferedOutputStream bos = new BufferedOutputStream(fos); 7 originBitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); 8 } catch (IOException e) { 9 10 }
在解决问题中,查阅了解了一些图片相关知识,更有利于了解图片压缩的过程和选择,有兴趣请移步:https://www.cnblogs.com/hellodingc/p/12497042.html
浙公网安备 33010602011771号