PNG 压缩级别、行滤波器(Filter)与调色板量化(Palette)
PNG 经常被误认为“只有无损、体积大且无法调优”。实际上,libvips 的 pngsave 同时提供两条优化路径:
- 真彩色无损压缩调优:通过调节 zlib
Compression(0..9)与 PNG **行预测滤波器(Row Filter)**平衡编码 CPU 耗时与体积; - 8-bit 索引调色板量化(
Palette: true,类似 pngquant):将 32-bit RGBA 图像量化为最多 256 色的带半透明索引色板,体积通常比真彩色 PNG 减小 60% ~ 75%。

PNG 导出参数跨绑定对照
Section titled “PNG 导出参数跨绑定对照”| 参数项 | govips PngExportParams |
sharp .png(options) |
pyvips / vips CLI pngsave |
调优建议 |
|---|---|---|---|---|
| 压缩级别 | Compression(0..9,默认 6) |
compressionLevel(0..9,默认 6) |
compression=6 |
线上实时生成建议 4 ~ 6;静态资产离线打包可用 9 |
| 行预测滤波器 | Filter(PngFilterNone / All 等) |
adaptiveFiltering(布尔值) |
filter="none" / "all" |
扁平 UI 图标/调色板图用 None 更快更小;连续色调照片用 All |
| 开启调色板量化 | Palette: true |
palette: true |
palette=True / --palette |
开启后转为索引色 PNG(需 libvips 编译了 libimagequant 或 quantizr) |
| 调色板色彩数 / 位深 | Bitdepth(1 / 2 / 4 / 8) |
colours(2..256) / bitdepth |
bitdepth(或 colours) |
256 色对应 bitdepth=8;16 色小图标可用 bitdepth=4 |
| 量化质量与抖动 | Quality(0..100)、Dither(0..1) |
quality、dither、effort |
Q=85、dither=1.0、effort=7 |
降低 Dither(如 0.5)可让大面积纯色块在 deflate 压缩中获得更高压缩率 |
| 隔行扫描(Adam7) | Interlace: true |
progressive: true |
interlace=True |
不推荐开启:Adam7 通常会使 PNG 体积增大 10%~20% 且解码更慢 |
1. 真彩色无损 PNG 与行滤波器选择
Section titled “1. 真彩色无损 PNG 与行滤波器选择”PNG 在用 zlib 压缩前,会对每一行像素做差分预测(Sub、Up、Average、Paeth)。对于色块分明的扁平图标、二维码或线条图,禁用预测滤波(PngFilterNone / adaptiveFiltering: false)不仅编码速度提升数倍,输出体积往往还比自适应滤波更小:
params := vips.NewPngExportParams()params.Compression = 6params.Filter = vips.PngFilterNoneparams.Interlace = falseparams.StripMetadata = true
data, _, err := image.ExportPng(params)if err != nil { return err}return os.WriteFile("lossless.png", data, 0o644)import sharp from 'sharp';
await sharp('alpha-rings.svg') .png({ compressionLevel: 6, adaptiveFiltering: false, progressive: false, }) .toFile('lossless.png');import pyvips
image = pyvips.Image.new_from_file("alpha-rings.svg")image.write_to_file( "lossless.png", compression=6, filter="none", interlace=False, keep="none",)vips pngsave alpha-rings.svg lossless.png \ --compression 6 \ --filter none \ --keep none2. 8-bit 索引调色板量化(Palette PNG8)
Section titled “2. 8-bit 索引调色板量化(Palette PNG8)”当业务必须输出 .png 格式(例如兼容不支持 WebP 的旧客户端或邮件模板),但又希望大幅压缩带半透明阴影的徽章、贴纸和 UI 资源时,可以启用 Palette: true:
params := vips.NewPngExportParams()params.Palette = trueparams.Bitdepth = 8 // 最多 256 色params.Quality = 85 // 量化质量目标 (0..100)params.Dither = 0.8 // Floyd-Steinberg 抖动强度 (0.0..1.0)params.Compression = 6params.Filter = vips.PngFilterNone
data, _, err := image.ExportPng(params)if err != nil { return err}return os.WriteFile("palette-8bit.png", data, 0o644)import sharp from 'sharp';
await sharp('alpha-rings.svg') .png({ palette: true, colours: 256, quality: 85, dither: 0.8, effort: 7, compressionLevel: 6, }) .toFile('palette-8bit.png');import pyvips
image = pyvips.Image.new_from_file("alpha-rings.svg")image.write_to_file( "palette-8bit.png", palette=True, bitdepth=8, Q=85, dither=0.8, effort=7, compression=6, filter="none",)vips pngsave alpha-rings.svg palette-8bit.png \ --palette \ --bitdepth 8 \ --Q 85 \ --dither 0.8 \ --effort 7 \ --compression 6 \ --filter none