实验 / 压缩对比 · CompressionStream 与 Canvas→PNG 待审核
CompressionStream · Canvas→PNG

压缩对比 · CompressionStream 与 Canvas→PNG

同一份数据,分别用浏览器原生 CompressionStream(DEFLATE 或 gzip)与把字节伪装成像素、让 canvas 编码成 PNG 两种方式压缩,各自解压回原文校验往返一致性,并对比体积。体积同时给出原始字节数与 base64 字符数,后者才是塞进 URL 时的真实大小。

1 · 两种方式的往返与体积

图 1-1 · 两种压缩方式的往返校验与体积对照。可更换输入数据,观察原始字节数、压缩后字节数与 base64 字符数三者的差异,以及两种方式在小数据与高熵数据上的表现分野。

Canvas 方案把每 3 个字节塞进一个像素的 R、G、B 三个通道,再用 toDataURL("image/png") 让浏览器内置的 PNG 编码器做无损压缩。PNG 用的正是 zlib 的 DEFLATE,所以这条路本质上是复用了 PNG 的压缩器。

警示 · alpha 必须恒为 255。canvas 以预乘 alpha 存储像素,alpha 小于 255 时 getImageDataputImageData 的往返会因舍入破坏数据。实测 Chrome 151,写入 0 到 255 的灰阶再读回:alpha 取 255 时 256 个像素无一改变;取 254 时有 1 个像素偏差 1;取 128 时 127 个像素出现偏差,最大偏差 1;取 64 时 191 个像素出现偏差,最大偏差 2(核对于 2026-08)。用于承载数据时任何小于 255 的 alpha 都不可接受。

两种方式都是无损 DEFLATE,压缩率因而接近。但 Canvas 方案额外背着三项开销:PNG 的文件头、alpha 通道占掉四分之一却不载荷数据、以及 base64 编码带来的膨胀。对小数据与高熵数据,它常常不如直接用 CompressionStream

2 · 参考文献

  1. CompressionStream. MDN. 浏览器原生流式压缩 API,支持 gzip、deflate 与 deflate-raw。https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream
  2. Strieb, J. Compressing data with the canvas API. 把字节塞进像素 RGB 通道,借 canvas 的 PNG 编码器复用其 zlib 做无损压缩。https://jstrieb.github.io/posts/canvas-compress/
  3. HTMLCanvasElement.toDataURL(). MDN. 把 canvas 内容编码为 data URL,此处取 image/png 即内置 DEFLATE。https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL

相关链接