我们通常采用多种方式结合的方法实现图片压缩需求,这些方式包括质量压缩、尺寸压缩。本章将分别介绍这两种方式,并且最后将结合这两种方式实现图片压缩的最优解决方案。
1 质量压缩
设置bitmap options属性,降低图片的质量,但像素不会减少,options 属性的值为0-100,来实现压缩。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void compressImageToFile(Bitmap bmp,File file) { // 0-100 100为不压缩 int options = 100; ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 把压缩后的数据存放到baos中 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(); } }
|
2 尺寸压缩
通过缩放图片像素来减少图片所占内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public static void compressBitmapToFile(Bitmap bmp, File file){ // 尺寸压缩倍数,值越大,图片尺寸越小 int ratio = 2; // 压缩Bitmap到对应尺寸 Bitmap result = Bitmap.createBitmap(bmp.getWidth() / ratio, bmp.getHeight() / ratio, Config.ARGB_8888); Canvas canvas = new Canvas(result); Rect rect = new Rect(0, 0, bmp.getWidth() / ratio, bmp.getHeight() / ratio); canvas.drawBitmap(bmp, null, rect, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 把压缩后的数据存放到baos中 result.compress(Bitmap.CompressFormat.JPEG, 100 ,baos); try { FileOutputStream fos = new FileOutputStream(file); fos.write(baos.toByteArray()); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); } }
|
通过设置 Bitmap 的 Matrix 属性。(不失真)
1 2 3 4 5 6 7 8
| // 缩放的矩阵 Matrix scaleMatrix = new Matrix(); int width = originalBitmap.getWidth(); int height = originalBitmap.getHeight(); scaleMatrix.setScale(ratio, ratio, width / 2, heigith / 2); //实时变换的图片资源bitmap targetBitmap = Bitmap.createBitmap(originalBitmap, 0, 0, width, height, scaleMatrix, true);
|
设置图片采样率,减少图片像素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static void compressBitmap(String filePath, File file){ // 数值越高,图片像素越低 int inSampleSize = 2; BitmapFactory.Options options = new BitmapFactory.Options(); //采样率 options.inSampleSize = inSampleSize; Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 把压缩后的数据存放到baos中 bitmap.compress(Bitmap.CompressFormat.JPEG, 100 ,baos); try { FileOutputStream fos = new FileOutputStream(file); fos.write(baos.toByteArray()); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); } }
|
小知识
1、文件大小换算公式:
1Byte=8bit
1KB=1024Byte(字节)=8*1024bit
1MB=1024KB
1GB=1024MB
1TB=1024GB
2、图像占用内存空间的大小:分辨率 * 位深 / 8
分辨率:宽 * 高
位深度:指定图像中的每个像素可以使用的颜色信息数量。
每个像素使用的信息位数越多,可用的颜色就越多,颜色表现就更逼真。
例如:
一幅图像分辨率:1024*768,24位,则其大小计算如下:
大小 = 1024 * 768 * 24 / 8 = 2359296 byte = 2304 KB
3 最佳实践
实际使用过程中,首先是将图片的尺寸压缩到一定大小,然后降低图片的质量到特定的内存要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Bitmap obtainBitmap() { Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.imag); Bitmap bg = Bitmap.createBitmap(bitmap.getWidth() / 2, bitmap.getHeight() / 2, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bg); Rect rect = new Rect(0, 0, bitmap.getWidth() / 2, bitmap.getHeight() / 2); canvas.drawBitmap(bitmap, null, rect, null); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int quality = 100; //直到图片的大小小于100kb do { outputStream.reset(); bg.compress(Bitmap.CompressFormat.JPEG, quality, outputStream); quality = quality - 3; } while (outputStream.toByteArray().length / 1024 >= 100 && quality > 0); Bitmap result = BitmapFactory.decodeByteArray(outputStream.toByteArray(), 0, outputStream.size()); return result; }
|
参考资料
Android 图片压缩之多种压缩方式结合使用