Pngquant-图片压缩

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”

官网地址:https://pngquant.org/

Mac端安装使用

  • 1.官网下载pngquant,解压到pngquant目录;

  • 2.拷贝图片到pngquant目录;

  • 3.通过pngquant命令压缩图片:
    Pro:pngquant chenyulong01$ ./pngquant img.png;

  • 4.通过pngquant命令压缩多个图片:
    Pro:pngquant chenyulong01$ ./pngquant ./img/*.png

  • 5.将压缩后的-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数据块来看:

8950 4e47 0d0a 1a0a:这个是PNG图片的头,所有的PNG图片的头都是这一串编码,图片软件通过这串编码判定这个文件是不是PNG格式的图片。 0000 000d:iHDR数据块的长度(转十进制13)。 4948 4452:数据块的type,为IHDR,之后紧跟着是data。 0000 021c:图片宽度(转十进制540)。 0000 0492:图片高度(转十进制1170)。 08:图像深度。 02/03:颜色类型。 00:压缩算法。 00:滤波器方法。 00:非隔行扫描方法。 75 f6a0:循环冗余检测。 [详细参数看这里](https://www.cnblogs.com/ECJTUACM-873284962/p/8986391.html) 所有我们可以得到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
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface BaseVariant {
/**
* Returns file collection containing all raw Android resources, including the ones from
* transitive dependencies.
*
* <p><strong>This is an incubating API, and it can be changed or removed without
* notice.</strong>
*/
//返回包含所有原始Android资源的文件集合,包括来自传递依赖项的资源
//这是一个正在孵化的API,可以更改或删除它,恕不另行通知
@Incubating
@NonNull
FileCollection getAllRawAndroidResources();
}

在这个前提下,可以结合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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
McImageConfig {
isCheckSize true //Whether to detect image size,default true
optimizeType "Compress" //Optimize Type,"ConvertWebp" or "Compress",default "Compress", "CompressWebp" is a better compression ratio but it don't support api < 18
maxSize 1*1024*1024 //big image size threshold,default 1MB
enableWhenDebug false //switch in debug build,default true
isCheckPixels true // Whether to detect image pixels of width and height,default true
maxWidth 1000 //default 1000
maxHeight 1000 //default 1000
whiteList = [ //do not do any optimization for the images who in the list
"icon_launcher.png"
]
mctoolsDir "$rootDir"
isSupportAlphaWebp false //Whether support convert the Image with Alpha chanel to Webp,default false, the images with alpha chanels will be compressed.if config true, its need api level >=18 or do some compatible measures
multiThread true //Whether open multi-thread processing,default true
bigImageWhiteList = [] //do not detect big size or large pixels for the images who in the list
}

参考资料

图片压缩原理
PNG文件结构分析
PNG文件格式白皮书
手动生成一张PNG图片
PNG格式