同一张PNG换五种压法,体积差在颜色数上

挑 PNG 压缩工具时,只比最后的文件大小看着省事,谁小选谁,可这样说不清差距从哪来。同样把一张图标压到 4 KB 上下。有的工具是把颜色砍到了二十几种,有的只是换了一种压法。换一张图结果可能就反过来。这回换个看法,直接拆 PNG 里的块,看每个输出的颜色类型、调色板色数和 IDAT 大小。平时在网页里顺手压图我用的是图映 ImgIng imging.cn/ 的图片压缩。这次想弄清楚的是命令行那几样工具各自动了哪一步,表里就只放了 oxipng、zopflipng、pngquant、pngquant 接 oxipng 和 iLoveIMG 网页版。

样本是 Wikimedia Commons 上的 4 张公开图。分别是 512×512 的透明图标 Afro Mobile Icon、1570×2400 的透明插画、904×901 的照片 PNG 和 1873×1571 的截图。用到的版本和参数:pngquant 3.0.3(--quality=65-80 --speed 4)、oxipng 10.2.1(-o 4 --strip safe)和 zopflipng(-y --filters=01234mepb)。这些我跑在一台 Apple M4 的 Mac 上,每样只跑一次,日期是 2026-11-05。跟我一样不是科班出身的先记一句:IDAT 不是哪个工具的名字,它就是 PNG 里存像素数据的那一块。画质我没打分。下面只谈体积和块里看得到的东西。TinyPNG 本来也想放进来,可这次没拿到它的输出,表里就没有它的数字。

样本图:Wikimedia Commons(公有领域 / CC0 / CC BY 4.0),作者署名见文末。这张图要看每一格的第一行,原图、oxipng、zopflipng 三行写的都还是「真彩」。从 pngquant 那行开始变成「调色板 N 色」。IDAT 的数字也在这一行掉了一大截。

无损工具只换压法不动颜色

oxipng 和 zopflipng 都是无损的,像素一个不改。透明图标的原图是 RGBA。它实际用了 1,035 种颜色,IDAT 是 23,294 字节。oxipng 压完是 15,363 字节,zopflipng 是 15,023 字节。颜色类型还是 RGBA,色数也还是 1,035。透明插画省得更少,原图 220,260 字节。oxipng 只到 217,261 字节,zopflipng 到 211,689 字节。我猜无损工具在透明图上能动的只有 deflate 和每行选哪种过滤器。这部分能挤的空间本来就不大。

照片和截图那两格不一样。这两张原图都存成了 RGBA。可它们的 alpha 全是 255,等于背着一个用不上的通道。oxipng 顺手把这个通道去掉,存成了 RGB。照片解压后的原始数据从 3,258,917 字节降到 2,444,413 字节。文件从 1,247,867 变成 1,011,425。这一步也是无损的,叫「颜色类型缩减」。它跟压缩算法本身强不强没有关系。zopflipng 在照片上比 oxipng 小一点,是 1,001,255 字节。到了截图上它反而更大,1,180,008 对 1,121,084。原因我没查。还有一件怪事,zopflipng 单独压原图的数字和我 2026-10-29 跑的那次对不上,参数明明一样,这一行我只当单次参考。

体积差主要出在量化这一步

pngquant 那一行是另一回事。它把颜色收进一个调色板,每个像素只存一个索引,一个像素就从 4 字节变成了 1 字节。透明图标在 65--80 这档下只剩 23 色。解压后的原始数据从 1,049,088 字节降到 262,656 字节,差不多正好四分之一。文件是 4,171 字节,不到无损那两家的三分之一。透明插画留了 27 色、54,292 字节。照片留了 232 色、417,199 字节。截图留满 256 色、486,607 字节。四张图都比无损那两行小一大截。

色数设成多少影响也不小,至少对透明图是这样。我又跑了一遍不带 --quality 的默认档。图标一下留了 256 色,文件 8,079 字节,几乎是 65--80 档的两倍。截图上两档都是 256 色,只差两个字节(486,605 对 486,607)。我的理解是这张图标在 65--80 这档留 23 色就够了,默认档没有这道门槛,就把色数用到了 256。截图在 65--80 档就已经用满 256 色,两档自然差不多。这只是我从数字上倒推的,没去验证。

量化之后再跑oxipng只补一点

把 pngquant 的输出再交给 oxipng,四张分别到 3,823、50,468、386,812、456,427 字节。图标只少了 348 字节。截图少了三万多字节,比起量化那一刀都是零头。照片这格多一些。它从 417,199 降到 386,812,大约少了 7%。按我手上 12 张图的分组来算,透明的 6 张 pngquant 一步省 77.0%,接 oxipng 再多省 2.1 个百分点。照片 3 张是 66.3% 加 4.0,截图 3 张是 68.2% 加 1.9。照片组里有 2 张是全不透明的 RGBA。这个数别往所有照片 PNG 上套。顺序上我是先量化再无损。反过来先跑 oxipng 的话,那一步的成果会被量化整个重写掉。

iLoveIMG的输出已经没有余量

iLoveIMG 网页版的输出沿用 2026-10-29 实测那批,只有图标、插画和截图三张,照片那格是空的。拆开看三张全是调色板。图标 23 色、IDAT 3,767 字节、文件 3,924 字节。插画 32 色、52,325 字节。截图 256 色、459,187 字节。体积跟 pngquant 接 oxipng 很接近。图标还比 pngquant 单跑的 4,171 小。我把这三个文件又跑了一遍 oxipng,三张一个字节都没省下来。从表现看它做了调色板量化,又把 deflate 压满了。具体用的什么工具我不知道。像素和本机 pngquant 的结果我对过。两者并不一样,不是同一个输出。另外它要把图传上去处理,这是 2026-10-29 抓包看到的。TinyPNG 官网写的是靠减少颜色数来压,听着像同一类思路。可这次没有它的输出,块长什么样我说不了。

拿到别家输出先补跑一遍oxipng

挑工具时可以按这个顺序看。文件大小只是结果,先看颜色类型。还是 RGBA 的说明只做了无损。透明图走这条路在我这 6 张上只省了 11.4%。变成调色板的再看留了几色。同一张图标 23 色和 256 色体积差出将近一倍。照片和截图存成 PNG 的先看 alpha 是不是全 255。是的话无损工具就能先省一截,不用急着量化。最后拿任何工具的输出补跑一遍 oxipng -o 4 --strip safe。省下多少,就是它在压法上没做满的部分。这次 iLoveIMG 是 0,pngquant 单跑在照片上还剩 7% 左右。

没解决的是画质,图标砍到 23 色以后半透明边缘只剩 7 档 alpha。放大看会不会起毛边我没打分,这篇答不了。

样本署名(均来自 Wikimedia Commons,文件名即原页面标题):

  • Afro_Mobile_Icon.png:Ben plc(公有领域)
  • Anime_girl_publicdomainq.png:oksmith(CC0)
  • Steve_Selvin.png:UC Berkeley Public Health(CC BY 4.0)
  • 2020-06-29_Screenshot_The_Book_Fort_Monmouth_-_Fort_Montagu.png:Stefan Kühn(CC0)
相关推荐
Lank_M19 分钟前
PNG 有损压缩省下的体积,大头不在 deflate
前端
用户老李42 分钟前
相机模型与标定自学教程 02:外参 \[R | t] 与完整投影链路
前端
用户老李1 小时前
无线电自学教程 03:电路基础——从欧姆定律到 LC 谐振
前端
申君健24864182772021 小时前
ESM 源码发布 + 显式子路径导出
前端
大龄秃头程序员1 小时前
实践 iOS Touch 响应链:从 sendEvent 到 nextResponder 的完整闭环
前端
用户老李1 小时前
YOLO 目标检测自学教程 05:动手——从零实现 mini-YOLOv1
前端
用户老李1 小时前
视频编码自学教程 02:颜色与色彩空间——从 RGB 到 Y'CbCr 4:2:0
前端
用户老李1 小时前
无线电自学教程 02:数学工具箱——正弦、复数、相量与分贝
前端
lpp191 小时前
一个网页的完整一生:从敲网址到页面显示,中间发生了什么
前端