pngquant
pngquant是一个命令行实用程序,也是一个用于有损压缩PNG图像的库。转换后可以显著减小文件大小(通常高达70%),并保持完全的alpha透明度。生成的图像与所有web浏览器和操作系统兼容。具有以下特点:
结合矢量化运算的高质量的调色板。
独特的自适应抖动算法。
跨平台: windows , Mac OS X , Linux 。
可以与shell脚本、GUI和服务器端软件轻松地集成。
快速模式处理大量图像。
Options:请参阅 pngquant -h 完整的选项列表。
–ext new.png
为输出文件名设置自定义扩展。默认-or8.png或被-fs8.png使用。–quality min-max
指示pngquant使用达到或超过最高质量所需的最少量的颜色。如果转换结果的质量低于最低质量,图像将不会被保存(如果输出到标准输出,则会输出24位原始图像),pngquant并将以状态码99退出。
最小值和最大值是范围0(最差)到100(完美)的数字,类似于JPEG。
pngquant –quality=65-80 image.png–speed N, -sN
速度/品质取舍从1(蛮力)到10(最快)。默认值为3. Speed 10的质量下降了5%,但比默认的速度快了8倍。–iebug
IE6的解决方法,只显示完全不透明的像素。pngquant会使几乎不透明的像素完全不透明,并会避免创建新的透明颜色。–version
将版本信息打印到标准输出。-
-从stdin读取图像并将结果发送到stdout。–
停止参数的处理。这允许使用以开头的文件名-。如果您pngquant在脚本中使用,建议在文件名前加上:
pngquant $OPTIONS – “$FILE”
Mac端安装使用
1.官网下载pngquant,解压到pngquant目录;
2.拷贝图片到pngquant目录;
3.通过pngquant命令压缩图片:
Pro:pngquant chenyulong01$ ./pngquant img.png;4.通过pngquant命令压缩多个图片:
Pro:pngquant chenyulong01$ ./pngquant ./img/*.png5.将压缩后的-fs8.png移到新文件夹:
Pro:pngquant chenyulong01$ mkdir ./img/compress/Pro:pngquant chenyulong01$ mv ./img/*-fs8.png ./img/compress/
6.目录结构如下:
压缩前后文件对比
先看下效果图:
大小:从398kb降到了140kb,减少了258kb,优化率达到64.8%
文件类型:从24位png,转换成了8位png。
PNG图片主要有三个类型,分别为 PNG-8,PNG-24,PNG-32:
PNG 8:PNG 8中的8,其实指的是8bits,相当于用2^8(2的8次方)大小来存储一张图片的颜色种类,2^8等于256,也就是说PNG 8能存储256种颜色,一张图片如果颜色种类很少,将它设置成PNG 8得图片类型是非常适合的。
PNG 24:PNG 24中的24,相当于3乘以8 等于 24,就是用三个8bits分别去表示 R(红)、G(绿)、B(蓝)。R(0-255),G(0-255),B(0-255),可以表达256乘以256乘以256=16777216种颜色的图片,这样PNG 24就能比PNG 8表示色彩更丰富的图片。但是所占用的空间相对就更大了。
PNG 32:PNG 32中的32,相当于PNG 24 加上 8bits的透明颜色通道,就相当于R(红)、G(绿)、B(蓝)、A(透明)。R(0-255),G(0-255),B(0-255),A(0-255)。比PNG 24多了一个A(透明),也就是说PNG 32能表示跟PNG 24一样多的色彩,并且还支持256种透明的颜色,能表示更加丰富的图片颜色类型。
从file命令来看:
24位PNG(每通道8位 - 无alpha通道)
$ file img2.png
img2.png: PNG image data, 540 x 1170, 8-bit/color RGB, non-interlaced
8位PNG(256色):
$ file img2-fs8.png
img2-fs8.png: PNG image data, 540 x 1170, 8-bit colormap, non-interlaced
从png数据块来看:
Png图片类型
* 1.Truecolour with alpha:带alpha的Truecolour,每个像素由四个样本组成:红色、绿色、蓝色和alpha。 * 2.Greyscale with alpha:灰度带alpha,每个像素由两个样本组成:灰度和alpha。 * 3.Truecolour:真彩色,每个像素由三个样本组成:红色、绿色和蓝色。alpha通道可以由单个像素值表示。匹配的像素是完全透明的,其他所有像素都是完全不透明的。如果alpha通道没有以这种方式表示,则所有像素都是完全不透明的。 * 4.Greyscale:灰度,每个像素由一个样本组成:灰色。与前一种情况一样,alpha通道可以由单个像素值表示。如果alpha通道没有以这种方式表示,则所有像素都是完全不透明的。 * 5.Indexed-colour: 索引颜色,每个像素都包含一个调色板索引(以及相关的alpha值表,如果存在)。每个像素的格式取决于PNG图像类型和位深度。对于非索引颜色的PNG图像类型,位深度指定每个样本的位数,而不是每个像素的总位数。对于索引彩色图像,位深度指定每个调色板索引中的位数,而不是调色板或alpha表中颜色的采样深度。在像素内,根据PNG图像类型,采样按以下顺序显示。
- a.带alpha的真彩色:红、绿、蓝、alpha。
- b.带alpha的灰度:灰色,alpha。
- c.真彩色:红、绿、蓝。
- d.灰度:灰色。
- e.索引颜色:调色板索引。
索引彩色图像
如果不同像素值的数量为256或更少,且RGB采样深度不大于8,且alpha通道不存在或正好为8位深,或者每个像素是完全透明或完全不透明的,则称为索引颜色的替代表示可能更有效地进行编码。每个像素都被调色板中的索引替换。调色板是一个条目列表,每个条目包含三个8位样本(红色、绿色、蓝色)。如果存在alpha通道,则还存在8位alpha采样的并行表。 即使PNG图像没有索引颜色,也可以构建一个或多个建议调色板,以帮助只能显示有限数量颜色的观众。 对于索引彩色图像,编码器可以重新排列调色板,以便将具有最大alpha值的表格条目分组到最后。在这种情况下,表格可以用不包含这些条目的缩写形式进行编码。
PNG图片IDAT数据块图例
目标图:
$ $
target.jpg
真彩 7x7 IDAT数据块
索引 7x7 IDAT数据块
Png数据块表
数据块符号 |
数据块名称 |
多数据块 |
可选否 |
位置限制 |
||
IHDR | 文件头数据块 |
否 |
否 |
第一块 | ||
cHRM | 基色和白色点数据块 |
否 |
是 |
在PLTE和IDAT之前 | ||
gAMA | 图像γ数据块 |
否 |
是 |
在PLTE和IDAT之前 | ||
sBIT | 样本有效位数据块 |
否 |
是 |
在PLTE和IDAT之前 | ||
PLTE | 调色板数据块 |
否 |
是 |
在IDAT之前 | ||
bKGD | 背景颜色数据块 |
否 |
是 |
在PLTE之后IDAT之前 | ||
hIST | 图像直方图数据块 |
否 |
是 |
在PLTE之后IDAT之前 | ||
tRNS | 图像透明数据块 |
否 |
是 |
在PLTE之后IDAT之前 | ||
oFFs | (专用公共数据块) |
否 |
是 |
在IDAT之前 | ||
pHYs | 物理像素尺寸数据块 |
否 |
是 |
在IDAT之前 | ||
sCAL | (专用公共数据块) |
否 |
是 |
在IDAT之前 | ||
IDAT | 图像数据块 |
是 |
否 |
与其他IDAT连续 | ||
tIME | 图像最后修改时间数据块 |
否 |
是 |
无限制 | ||
tEXt | 文本信息数据块 |
是 |
是 |
无限制 | ||
zTXt | 压缩文本数据块 |
是 |
是 |
无限制 | ||
fRAc | (专用公共数据块) |
是 |
是 |
无限制 | ||
gIFg | (专用公共数据块) |
是 |
是 |
无限制 | ||
gIFt | (专用公共数据块) |
是 |
是 |
无限制 | ||
gIFx | (专用公共数据块) |
是 |
是 |
无限制 | ||
IEND | 图像结束数据 |
否 |
否 |
最后一个数据块 |
安卓图片压缩
首先在Android Gradle Plugin版本为不低于3.3的情况下,有一个接口BaseVariantImpl.allRawAndroidResources.files可以在编译期间获取到所有的资源文件。所有包含jar,aar,module等等。
1 | public interface BaseVariant { |
在这个前提下,可以结合pngquant,编写一个无侵入性的图片压缩插件,可以在构建过程中对所有图片进行有配置的压缩,从而减少包对体积大小。具体实现可以看抖音的开源McImage插件介绍https://github.com/smallSohoSolo/McImage:
优势:McImage在编译期间 hook 资源,采用开源的算法 pngquant/guetzli 进行压缩,支持 webp 压缩。与 tinypng 等一些已知的方案相比,存在以下优势:
- McImage 现支持 webp 压缩,压缩比高于 tinypng,不过 Android 上 webp 需要做兼容,下文会详细介绍;
- tinypng 不开源,每个账号每个月只能免费压缩 500 张;McImage 使用的压缩算法都是基于开源算法;
- McImage 不仅可以压缩 module 中的图片,还能压缩 jar 和 aar 中的图片;
- McImage 支持压缩算法扩展,有更优的压缩算法选择时扩展方便;
- 和行业里其他方案相比,McImage 还能够支持压缩包含透明度的 webp 图片,并且兼容了 aapt2 对资源的 hook。
收益:McImage 支持两种优化方式,但是两种优化方式不可同时使用:
- Compress,pngquant 压缩 png 图片,guetzli 压缩 jpg 图片;
- ConvertWebp,webp 压缩 png\png 图片。
- Webp 的压缩比要高于 pngquant、guetzli,推荐使用 ConvertWebp 压缩方式。
功能:除了压缩、优化图片,McImage 还提供了以下功能:
- 大图检测。阈值可在 McImageConfig 里进行设置,方便大图复盘优化包大小;也支持编译阶段检测,检测到大图直接 block 编译,可及时发现大图提交;
- 压缩算法方便扩展。如果想接入其他压缩算法,只需要继承 AbstractTask,实现 ITask 接口中的 work 方法即可;
- 支持多线程压缩。把所有 task 的执行放入线程池中执行,大大缩短了 mcimage 的执行时间;
- 增加了图片缓存 cache,进一步缩短打包时间。在开启多线程+图片缓存的情况下,全部命中缓存的情况下,整个 mcimage 的过程不到 10s;缓存路径可配置;
- 压缩质量可配置,满足不同的压缩质量需求,缓存文件也会按照不同的压缩质量进行保存和命中;
- 图片白名单功能;
- debug打包模式是否开启设置;
配置文件代码:
1 | McImageConfig { |
参考资料
图片压缩原理
PNG文件结构分析
PNG文件格式白皮书
手动生成一张PNG图片
PNG格式
Ursprünglicher Link: http://nunu03.github.io/2021/12/27/Pngquant-图片压缩/
Copyright-Erklärung: 转载请注明出处.