Image 自定义图像格式:如何针对压缩算法

Image 自定义图像格式:如何针对压缩算法,image,compression,png,deflate,quantization,Image,Compression,Png,Deflate,Quantization,在过去的几天里,我对PNG做了一些修改,我对我的发现感到不安。我的结论是,我的大部分结果都与压缩有关。所以这个周末我将深入阅读高级压缩文章。我想分享我目前的发现。看看是否有人对实现我的目标有什么建议,也许能给我指出正确的方向 我目前正在进行一个项目,我需要在不到15秒的时间内获得尽可能小的文件大小 我正在处理的大多数图像都是PNG-8bpp,带有完整的256色调色板。我可以用5bpp(32种颜色)准确地表示这些图像中的大多数 但是,PNG索引仅支持1、2、4和8bpp。因此,我的想法是将PNG格

在过去的几天里,我对PNG做了一些修改,我对我的发现感到不安。我的结论是,我的大部分结果都与压缩有关。所以这个周末我将深入阅读高级压缩文章。我想分享我目前的发现。看看是否有人对实现我的目标有什么建议,也许能给我指出正确的方向

我目前正在进行一个项目,我需要在不到15秒的时间内获得尽可能小的文件大小

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

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

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种颜色可在5bpp中以32种颜色表示。使用上述相同的技术,我能够获得比未压缩好得多的结果,但再次在压缩时失败。最终尺寸压缩。。。84KB。然后我试着在6,7页。。。与8bpp时的压缩效果相同

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


为什么会这样?我是否可以调整/修改压缩算法,以使用5、6或7bpp格式的类似PNG的格式作为目标,该格式使用8bpp压缩?值得花时间吗。。。是的,再节省10KB是值得的。

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

即使过滤不是问题,平面压缩的工作方式,将像素大小从8位减少到7位或6位也不会有多大效果,因为它还假定符号大小为8位

总之,使用奇数像素的唯一好处是,未压缩的数据会更小。通过打破像素的字节边界对称性,您将无法获得PNG压缩的大部分好处


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

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

  • 查找重复的字节序列并将其编码为反向引用
  • 使用哈夫曼编码对字节进行编码
通过从8位更改像素长度,您将与字节边界不同步,并且DEFLATE将无法将重复的像素运行编码为重复的字节


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

在每个扫描线之前,过滤字节将始终为零。据我所知,在索引图像中过滤通常是没有好处的。因此,我还剥离了过滤器字节以节省空间。我也不必使用deflate来压缩IDAT部分。。。我还在测试其他的压缩算法设置,看看是否可以减少bpp。过滤对索引图像是有益的;这取决于图像。正如我上面所说的,你正在损害PNG过滤和寻找重复字节(而不是像素)的平面压缩的好处。如果你有连续色调(照片类型)的图像,你不会得到比JPEG更好的压缩。对于卡通画或线条画,LZW(GIF)对于奇数像素尺寸的效果更好。在我进行的测试中,GIF文件的大小在5-7bpp之间,没有比具有相同缩小调色板的PNG8小。我能够使用6bpp实现更好的压缩,并使用模式填充最后两位,而不是最初的PNG8。我想知道是否有一种方法可以设置一个压缩器,每x字节数查找一个模式?所以对于6bpp,我希望每3个字节有一个模式。我将尝试使用LZMA和lc lp p Switchs。如果坚持使用正确的符号大小,FLATE(PNG)压缩比LZW(GIF)压缩要好。填充到8bpp效果更好,这是有道理的。我的观点是关于使用奇数(3/5/6/7)尺寸。