PNG 图片压缩
Pngquant
既然是缩减包大小,当然是有损压缩收益更高,而且,人眼对于图像之间的细微差异根本难以辩别,所以,我们选择有损压缩。
无论是从压缩效果和使用便利性来看,pngquant在新窗口打开 的表现都是相当令人惊艳,但是有一个很重要的问题,pngquant在新窗口打开 虽然是开源软件,但它是 GPL License在新窗口打开,而 Booster 是 Apache License在新窗口打开,如何既能避开法务风险,又能使用优秀的 GPL License在新窗口打开 软件呢?
Command SPI
为了解决开源协议的冲突问题,Booster 专门为此提供了 Command SPI在新窗口打开,将 API 与实现进行分离,API 采用 Apache License在新窗口打开,实现采用 GPL License在新窗口打开,通过 SPI (Service Provider Interface)在新窗口打开 完美的解决了这一问题。
Pngquant Provider
booster-pngquant-provider在新窗口打开 作为 pngquant 命令的提供者,采用 GPL License在新窗口打开 独立开源,目前内置了 Linux, macOS, Windows 三个平台的 pngquant 二进制可执行文件 64 位版本。
实现思路
根据 Android 的构建流程,我们选择在 mergeRes 和 processRes 任务之间插入 PNG 压缩任务,如下图所示:
自 AGP 3.0.0 开始,AAPT2 默认会被开启,由于 AAPT2 采用了 AAPT2 Container 格式在新窗口打开 (文件后缀为 .flat) 所以,需要在压缩之前需要明确,项目中是否开启 android.enableAapt2 的选项,因此 Booster 根据 AAPT2 选项分不同的 task 来处理:
注意
由于 AAPT 1.0 已经成为过去式,Booster 只支持启用 AAPT2 的情况。
如何使用
在使用 booster-task-compression-pngquant在新窗口打开 的时候,还需要引入 booster-pngquant-provider在新窗口打开,如下所示:
buildscript {
    ext {
        kotlin_version = "1.5.31"
        booster_version = "4.16.3"
    }
    repositories {
        mavenLocal()
        mavenCentral()
        google()
        jcenter()
        maven { url 'https://oss.sonatype.org/content/repositories/public/' }
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "com.didiglobal.booster:booster-gradle-plugin:$booster_version"
        /* 👇👇👇👇 引用这两个模块 👇👇👇👇 */
        classpath "com.didiglobal.booster:booster-task-compression-pngquant:$booster_version"
        classpath "io.johnsonlee.booster:booster-pngquant-provider:2.3.0"
    }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
然后,执行 compress{Variant}ResourcesWithPngquant 任务来完成对图片资源的压缩,如下所示:
$ ./gradlew compressDebugResourcesWithPngquant --info
注意
Android Gradle Plugin 3.6 及以上版本,需要在 gradle.properties 中设置:
android.precompileDependenciesResources=false
注意
Android Gradle Plugin 7.0 及以上版本,需要在 gradle.properties 中设置:
android.enableSourceSetPathsMap=false
自定义压缩质量
booster-task-compression-pngquant在新窗口打开 支持自定义的参数如下表所示:
| 选项 | 描述 | 
|---|---|
| booster.task.compression.pngquant.option.quality | 压缩质量 (默认 80) | 
| booster.task.compression.pngquant.option.speed | 压缩速度 (默认 3) | 
通过 gradle.properties 配置
booster.task.compression.pngquant.option.quality=75
booster.task.compression.pngquant.option.speed=1
2
通过命令行配置
$ ./gradlew assembleDebug \
    -Pbooster.task.compression.pngquant.option.quality=75 \
    -Pbooster.task.compression.pngquant.option.speed=1
2
3
任务报告
当 compress${Variant}ResourcesWithPngquant 任务执行完成后会自动在以下路径中生成任务报告:
build/reports/booster-task-compression-pngquant/${variant}/report.txt
其内容如下所示:
50.37% intermediates/res/merged/debug/mipmap-xxxhdpi_ic_launcher_round.png.flat 7,622 15,132 ...
46.30% intermediates/res/merged/debug/mipmap-xxhdpi_ic_launcher_round.png.flat  4,821 10,413 ...
45.95% intermediates/res/merged/debug/mipmap-xxxhdpi_ic_launcher.png.flat       4,194  9,128 ...
42.31% intermediates/res/merged/debug/mipmap-xhdpi_ic_launcher_round.png.flat   2,917  6,895 ...
39.31% intermediates/res/merged/debug/mipmap-xxhdpi_ic_launcher.png.flat        2,511  6,387 ...
36.88% intermediates/res/merged/debug/mipmap-hdpi_ic_launcher_round.png.flat    1,809  4,905 ...
34.90% intermediates/res/merged/debug/mipmap-xhdpi_ic_launcher.png.flat         1,567  4,490 ...
20.72% intermediates/res/merged/debug/mipmap-hdpi_ic_launcher.png.flat            614  2,963 ...
18.51% intermediates/res/merged/debug/mipmap-mdpi_ic_launcher_round.png.flat      515  2,783 ...
 7.09% intermediates/res/merged/debug/mipmap-mdpi_ic_launcher.png.flat            146  2,060 ...
-------------------------------------------------------------------------------------
 TOTAL                                                                         26,716
2
3
4
5
6
7
8
9
10
11
12
其中,各列涵义如下所示:
- 压缩率 (压缩前的大小 - 压缩后的大小) / 压缩前的大小
- 合并后的资源文件路径
- 压缩后的大小
- 压缩前的大小
- 原始路径
