开源一个 Android 图片压缩框架

  1. 先通过设置 Options 的 inJustDecodeBounds 为 true,来加载图片,以得到图片的尺寸信息。此时图片不会被加载到内存中,所以不会造成 OOM,同时我们可以通过 Options 得到原图的尺寸信息。
  2. 根据上一步中得到的图片的尺寸信息,计算一个 inSampleSize,然后将 inJustDecodeBounds 设置为 false,以加载采样之后的图片到内存中。

关于 inSampleSize 需要简单说明一下:inSampleSize 代表压缩后的图像一个像素点代表了原来的几个像素点,例如 inSampleSize 为 4,则压缩后的图像的宽高是原来的 1/4,像素点数是原来的 1/16,inSampleSize 一般会选择 2 的指数,如果不是 2 的指数,内部计算的时候也会向 2 的指数靠近。所以,实际使用过程中,我们会通过明确指定 inSampleSize 为 2 的指数,来避免内部计算导致的不确定性。

1.3 双线性采样

邻近采样可以对图片的尺寸进行有效的控制,但是它存在几个问题。比如,当我需要把图片的宽度压缩到 1200 左右的时候,如果原始的图片的宽度压是 3200,那么我只能通过设置 inSampleSize 将采样率设置为 2 来将其压缩到 1600. 此时图片的尺寸比我们的要求要大。就是说,邻近采样无法对图片的尺寸进行更加精准的控制。如果需要对图片尺寸进行更加精准的控制,那么就需要使用双线性压缩了。

双线性采样采用双线性插值算法,相比邻近采样简单粗暴的选择一个像素点代替其他像素点,双线性采样参考源像素相应位置周围 2x2 个点的值,根据相对位置取对应的权重,经过计算得到目标图像。

它在 Android 中的使用也比较简单,

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blue_red);
Matrix matrix = new Matrix();
matrix.setScale(0.5f, 0.5f);
Bitmap sclaedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth()/2, bitmap.getHeight()/2, matrix, true);

也就是对得到的 Bitmap 应用 createBitmap() 进行处理,并传入 Matrix 指定图片尺寸放缩的比例。该方法返回的 Bitmap 就是双线性压缩之后的结果。

1.4 图片压缩算法总结

在实际使用过程中,我们通常会结合三种压缩方式使用,一般使用的步骤如下,

  1. 使用邻近采样对原始的图片进行采样,将图片控制到比目标尺寸稍大的大小,防止 OOM;
  2. 使用双线性采样对图片的尺寸进行压缩,控制图片的尺寸为目标的大小;
  3. 对上述两个步骤之后得到的图片 Bitmap 进行质量压缩,并将其输出到磁盘上。

当然,本质上 Android 图片的编码是由 Skia 库来完成的,所以,除了使用 Android 自带的库进行压缩,我们还可以调用外部的库进行压缩。为了追求更高的压缩效率,通常我们会在 Native 层对图片进行处理,这将涉及 JNI 的知识。笔者曾在之前的文章 《在 Android 中使用 JNI 的总结》 中介绍过 Android 平台上 JNI 的调用的常规思路,感兴趣的同学可以参考下。

2、Github 上的开源的图片压缩库

现在 Github 上的图片压缩框架主要有 Luban 和 Compressor 两个。Star 的数量也比较高,一个 9K,另一个 4K. 但是,这两个图片压缩的库有各自的优点和缺点。下面我们通过一个表格总结一下:

框架 优点 缺点
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Image Cropper 是一个开源的图片裁剪框架,它可以让你在 Android 应用中实现图片裁剪功能。使用 Android Image Cropper,你可以让用户在任何地方选择一张图片并对其进行裁剪。该框架支持手势缩放、旋转、裁剪框大小调整等功能。 Android Image Cropper 的主要功能如下: - 矩形和圆形裁剪框 - 支持手势缩放、旋转、裁剪框大小调整 - 支持设置裁剪框宽高比、最大最小裁剪框大小、裁剪结果大小等 - 支持设置裁剪结果压缩质量、格式等 - 支持自定义裁剪界面 下面是使用 Android Image Cropper 的基本步骤: 1. 在 build.gradle 文件中添加以下依赖项: ``` implementation 'com.github.yalantis:ucrop:2.2.6' ``` 2. 在你的Activity中,启动裁剪界面: ``` // 从相册中选择一张图片进行裁剪 UCrop.of(sourceUri, destinationUri) .withAspectRatio(16, 9) .withMaxResultSize(maxWidth, maxHeight) .start(this); // 或者从相机中拍照裁剪 UCrop.of(sourceUri, destinationUri) .withAspectRatio(16, 9) .withMaxResultSize(maxWidth, maxHeight) .start(this); ``` 3. 在 onActivityResult() 方法中获取裁剪结果: ``` @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == UCrop.REQUEST_CROP && resultCode == RESULT_OK) { final Uri resultUri = UCrop.getOutput(data); // 处理裁剪结果 } else if (resultCode == UCrop.RESULT_ERROR) { final Throwable cropError = UCrop.getError(data); // 处理裁剪错误 } } ``` 希望这些信息能够帮助你快速了解 Android Image Cropper。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值