在 Android 开发中,图片压缩是一个重要的优化手段,旨在提升用户体验、减少网络传输量以及降低存储空间占用。以下是几种主流的图片压缩方法,结合原理、使用场景和优缺点进行详细解析。
质量压缩法通过降低图片的压缩质量(如 JPEG 的压缩率)来减小文件大小。这种方法不会改变图片的分辨率(宽高不变),但会减少图片的文件体积。
通过设置 Bitmap.CompressFormat
和压缩质量参数来实现。
代码示例:
//传入的参数为bitmap
private Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 第一次压缩,质量为 100(不压缩)
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
int options = 100;
// 循环压缩直到满足条件
while (baos.toByteArray().length / 1024 > 100) {
baos.reset();
image.compress(Bitmap.CompressFormat.JPEG, options, baos);
options -= 10;
}
// 生成压缩后的 Bitmap
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
return BitmapFactory.decodeStream(isBm);
}
注意:质量压缩需要按照个人需求去进行调整,示例写了100,没有进行压缩,大家可以尝试一下压缩到50,然后跟原图进行一个对比。
优点:
缺点:
采样率压缩法通过减少图片的分辨率(降低像素数量)来减小文件大小。通过设置 BitmapFactory.Options.inSampleSize
,可以控制图片的缩放比例。
通过设置 inSampleSize
来实现采样率压缩。
代码示例:
//传入的参数为图片的路径
private Bitmap getimage(String srcPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 仅读取图片的宽高,不加载图片到内存
newOpts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(srcPath, newOpts);
newOpts.inJustDecodeBounds = false;
// 根据需求计算采样率
int w = newOpts.outWidth;
int h = newOpts.outHeight;
float hh = 1280f; // 目标高度
float ww = 720f; // 目标宽度
int be = 1;
// 根据宽度或高度计算采样率
if (w > h && w > ww) {
be = (int) (w / ww);
} else if (h > w && h > hh) {
be = (int) (h / hh);
}
newOpts.inSampleSize = be;
// 重新加载图片
return BitmapFactory.decodeFile(srcPath, newOpts);
}
优点:
缺点:
缩放法通过调整图片的尺寸(缩放宽高)来减小文件大小。通过 Bitmap.createBitmap()
和 Canvas
绘制缩放后的图片,可以实现尺寸压缩。
通过创建 Canvas
和 Matrix
进行缩放。
代码示例:
//传入的参数为bitmpa,还有需要保存文件的路径
public static void compressBitmapToFile(Bitmap bmp, File file) {
int ratio = 2; // 缩放比例
// 创建缩放后的 Bitmap
Bitmap result = Bitmap.createBitmap(bmp.getWidth() / ratio,
bmp.getHeight() / ratio,
Bitmap.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();
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();
}
}
注意:上面的示例方法中,可以直接去掉file的相关逻辑,返回result就可以了
public static Bitmap compressBitmap(Bitmap bmp) {
int ratio = 2; // 缩放比例
// 创建缩放后的 Bitmap
Bitmap result = Bitmap.createBitmap(
bmp.getWidth() / ratio,
bmp.getHeight() / ratio,
Bitmap.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);
return result; // 直接返回缩放后的 Bitmap
}
优点:
缺点:
方法类型 | 优点 | 缺点 |
---|---|---|
质量压缩法 | - 保持图片质量较高 - 实现简单 |
- 内存占用不变 - 高压缩率可能导致模糊 |
采样率压缩法 | - 显著减少文件大小和内存占用 - 支持灵活设置采样率 |
- 可能导致图片模糊 - 需要手动计算采样率 |
缩放法 | - 精确控制图片尺寸 - 适用于生成适配图片或缩略图 |
- 多次缩放可能导致失真 - 实现相对复杂 |
通过以上几种方法的结合使用,可以根据具体需求选择合适的压缩策略,从而优化 Android 应用的性能和用户体验。
如果您觉得这篇文章对您有所帮助,
欢迎收藏、点赞和分享,让更多开发者受益!
你们的支持是我持续创作的动力!
如果大家对压缩的原理感兴趣,后面我会逐步更新相关方法的原理,欢迎大家在评论区相互交流