一、背景介绍
目前公司的Android项目都使用了WebP插件进行图片的优化。该插件主要是在线上打包系统进行build时才会进行的一个图片优化的动作。通过将PNG图片转换成webp格式减少包体积大小。目前最新的插件版本是1.0.4
二、当前WebP插件的实现
插件的实现机制比较简单,主要是通过三个Gradle Task来完成:
- DownloadLibTask
从https://storage.googleapis.com/downloads.webmproject.org/releases/webp/下载对应操作系统的webp工具包。 - DecompressTask
将下载的压缩包解压到特定目录 - ConvertTask
在对drawable资源遍历过程中,使用cwebp命令行工具,对其进行格式转换1
cwebpPath + " -q " + getQuality() + " " + srcFilePath + " -o " + dstFilePath;
通过将dependsOn设定task的依赖关系链,从而完成一系列操作。1
2
3
4
5private void attachCovertTaskToBuild(Project project, String variant, Task convertTask) {
String nameOfMergeResources = "convertPics";
Task mergeResources = project.getTasks().findByName(nameOfMergeResources);
mergeResources.dependsOn(convertTask);
}
1 | convertTask.dependsOn(decompressTask.dependsOn(downloadTask)); |
三、当前WebP插件的问题
1. 在线下载不稳定
由于webp命令工具包是在线下载的,因此遇到网络连接失败的时候工具包无法下载,也就导致在线打的包是没有经过图片压缩的,因此包体积可能会大幅增加。试想一下,如果发版前打包出现下载失败的情况是多可怕!另一方面,官方工具包的下载地址也可能会变迁,一旦变迁,也会出现无法进行图片压缩的情况。
对于https://storage.googleapis.com/downloads.webmproject.org/releases/webp/在windows系统下就无法下载到对应的工具包
2. 有些png无法转换格式
在实际打出来的apk包中,依然可以看到有很多png图片存在。说明cwebp在对某些特殊格式的png图片是无法进行webp化的。但是通过tinypng依然可以压缩很多。
3. 压缩体积并不是最优
通过对比tinypng和cwebp转换同一个png图片,可以发现tinypng压缩后的图片要比cwebp的还要小。
四、如何改进
1. TinyPNG?
tinypng平时使用较多,但是用在插件里会存在三个明显的缺陷:
- 第一是通过API方式进行压缩,也就是走在线方式,速度会比较慢,尤其是涉及到一个APP中大量png进行处理的时候;
- 第二如果涉及到tinypng服务不稳定的时候,也会出现png不被压缩的情况;
- 第三是其每一个API Key每月只能免费压缩500张图片,虽然可以多申请一些API Key进行动态替换,但是维护工作过于繁琐。
2. PngQuant
通过以上分析,我们可以明确两个基本改进思想: - PNG压缩需要本地化,避免线上异常环境的出现
- 抛弃webp方式改用类tinypng方式,主要是为了实现png压缩的最大化
通过调研,发现PngQuant这个不错的类库https://pngquant.org/。 按照官网描述,其Features主要有: - High-quality palette generation using a combination of vector quantization algorithms.
- Unique adaptive dithering algorithm that adds less noise to images than the standard Floyd-Steinberg.
- Easy to integrate with shell scripts, GUIs and server-side software.
- Fast mode for real-time processing/large numbers of images.
通过实际体验发现该库非常好用,压缩效果很好。有部分文档指出tinypng同时采用了pngquant、optipng、advpng几种脚本。3. 具体实现
- 命令行工具本地化
将不同平台的pngquant命令行工具打入插件包中,避免从网上下载。需要注意的是,官网提供了windows和mac系统的命令行工具,linux系统下需要自己编译或者从对应源进行更新。目前公司的打包机使用的是centoOS。 - ExtractPngToolTask
插件开始工作时,根据当前运行的系统,将对应的命令行工具copy到特定目录。 - PngCompressTask
使用pngquant进行图片压缩1
pngToolPath + " --quality=65-80 " + filePath + " -o " + filePath + " -f"
目前最新版本1.0.5,已上传maven库,可以直接替换使用。
五、潜在风险
使用这种方式压缩的图片还需要UI设计进行审核,避免出现图片压缩导致视觉效果变差。
项目地址https://gitlab.pri.ibanyu.com/gaoguowei9199/webp_plugin,欢迎讨论