压缩对比 · CompressionStream 与 Canvas→PNG
同一份数据,分别用浏览器原生 CompressionStream(DEFLATE 或 gzip)与把字节伪装成像素、让 canvas 编码成 PNG 两种方式压缩,各自解压回原文校验往返一致性,并对比体积。体积同时给出原始字节数与 base64 字符数,后者才是塞进 URL
时的真实大小。
1 · 两种方式的往返与体积
Canvas 方案把每 3 个字节塞进一个像素的 R、G、B 三个通道,再用 toDataURL("image/png") 让浏览器内置的 PNG 编码器做无损压缩。PNG 用的正是 zlib 的 DEFLATE,所以这条路本质上是复用了 PNG 的压缩器。
警示 · alpha 必须恒为 255。canvas 以预乘 alpha 存储像素,alpha 小于 255 时 getImageData 与 putImageData 的往返会因舍入破坏数据。实测 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 · 参考文献
- CompressionStream. MDN. 浏览器原生流式压缩 API,支持 gzip、deflate 与 deflate-raw。https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream
- Strieb, J. Compressing data with the canvas API. 把字节塞进像素 RGB 通道,借 canvas 的 PNG 编码器复用其 zlib 做无损压缩。https://jstrieb.github.io/posts/canvas-compress/
- HTMLCanvasElement.toDataURL(). MDN. 把 canvas 内容编码为 data URL,此处取
image/png即内置 DEFLATE。https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
相关链接
- CompressionStream developer.mozilla.org 浏览器原生流式压缩 API,支持 gzip、deflate 与 deflate-raw。
- Compressing data with the canvas API jstrieb.github.io 把字节塞进像素 RGB 通道,借 canvas 的 PNG 编码器复用其 zlib 做无损压缩。
- HTMLCanvasElement.toDataURL() developer.mozilla.org 把 canvas 内容编码为 data URL,此处取 image/png 即内置 DEFLATE。