自定义图像格式:如何定位压缩算法

时间:2012-02-24 19:32:53

标签: image compression png deflate quantization

在过去的几天里,我对PNG进行了一些调整,我对我的发现感到不满。我的结论是我的大多数结果都与压缩有关。所以本周末我将深入研究高级压缩文章。到目前为止,我想分享我的发现。看看是否有人对实现我的目标有任何建议,并且可能指出我正确的方向。

我目前正在开展一个项目,我需要在不到15秒的窗口内获得尽可能小的文件大小。

我使用的大部分图像都是PNG-8bpp,带有完整的256色调色板。大多数这些图像我可以用5bpp(32种颜色)准确表示。

然而,

PNG索引仅支持1,2,4和8bpp。所以我的想法是将PNG格式剥离到我需要的最小信息,并编写一个编码器/解码器来支持3,5,6或7bpp的IDAT部分。

Test 1:
Original File: 61.5KB, 750 * 500, 8pp Palette, 256 colors, No tRNS
After Optimizations (Reductions to 4bpp, Strip Anx Chunks, & PNGOUT): 49.2KB 4bpp, 16 Colors
Human Interpretation: I can see 6 distinguishable colors.

由于我只需要六种颜色来表示图像,我决定使用3bpp对IDAT进行编码,以便为我提供8种颜色的最大调色板。首先,我解压缩了IDAT,导致新文件大小为368KB。在向IDAT应用3bpp后,我的新未压缩文件大小为274KB。我接下来似乎是一个好的开始...接下来我将deflate应用到我的新IDAT部分。结果...... 59KB。

比使用4bpp大10KB。

Test 2:
Original File: 102KB, 1000 * 750, 8bpp, 256 Colors, tRNS 1 fully transparent color
After Optimization: 79KB, 8bpp, 193 colors, tRNS 1 full transparent color
Human Interpretation: I need about 24 colors to represent this picture.

24种颜色可以用32种颜色表示为5bpp。使用上面相同的技术,我能够在未压缩的情况下获得更好的结果,但同样在压缩时我失败了。最终尺寸压缩... 84KB。然后我尝试了6,7bpp ...相同的结果压缩得比较差,在8bpp。

为了确保我保存了所有未压缩的图像并尝试了其他几种压缩算法...... LZMA,BZIP2,PAQ8 ......相同的结果是压缩尺寸小于8bpp而不是5,6,或者7bpp和更小尺寸的4bpp比在3bpp。

为什么会这样?我可以调整/修改压缩算法以定位PNG格式,使用5,6或7bpp格式进行8bpp压缩吗?是否值得花时间......是的,另外保存10KB是值得的。

2 个答案:

答案 0 :(得分:2)

您所看到的是,通过使用奇数像素大小,由于PNG压缩的工作方式,您的有效压缩会减少。仅仅使用直接FLATE / ZIP压缩的PNG压缩的优点是过滤。 PNG压缩试图利用一小部分预处理过滤器来利用水平和垂直对称性。这些滤波器在字节边界上工作,对像素大小为4/8/16/24/32/48/64位有效。当您移动到奇数大小的像素(3/5/6/7位)时,您正在击败滤波,因为在8位边界上过滤时,相同颜色的像素不会“水平相互抵消”。

即使滤波不是问题,FLATE压缩的工作方式,将像素大小从8位减少到7位或6位也不会产生太大影响,因为它也假定符号大小为8位。

总之......使用奇数像素可以实现的唯一好处是未压缩数据会更小。通过打破像素的字节边界对称性,您将失去PNG压缩的许多好处。

GIF压缩支持1到8位的所有像素大小。它将符号大小定义为像素大小,不使用任何预过滤。如果压缩为7位像素,8位GIF图像不会受到较少的压缩,但也不会受益,因为压缩更多地取决于像素的重复而不是符号大小。

答案 1 :(得分:0)

PNG使用的DEFLATE压缩有两种主要技术:

  • 找到重复的字节序列,并将它们编码为反向引用
  • 使用霍夫曼编码对字节进行编码

通过将像素长度从8位更改为与字节边界不同步,DEFLATE将无法将重复像素运行编码为重复字节。

由于霍夫曼编码,8位像素有未使用的位并不重要,因为编码将使用可变宽度代码编码字节,将最短的代码分配给最常出现的值。