Android图片压缩方略

Catalogue
  1. 1 质量压缩
  2. 2 尺寸压缩
  3. 3 最佳实践
  4. 参考资料

我们通常采用多种方式结合的方法实现图片压缩需求,这些方式包括质量压缩、尺寸压缩。本章将分别介绍这两种方式,并且最后将结合这两种方式实现图片压缩的最优解决方案。

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 图片压缩之多种压缩方式结合使用