了解PNG文件格式IDAT段

4
从下面的示例图像中,我有一个黄色的边框仅供显示目的。
实际的.png文件是一个简单的黑白图像,3像素乘以3像素。我最初想尝试作为2x2,但这不会帮助解释低/高与高/低的绘图流。至少这样,从上面来说,我会有两个黑色,一个白色,或者一个白色,从下面来说是两个黑色。
所以,我读取数据块,到达IDAT块,解码(zlib)并得到以下12字节
00 20 00 40 00 80
我的问题是,如何将上述内容分解为3 x 3的黑白样品... 另外,它保存在调色板格式中,并正确识别1比特的位深度和2个颜色调色板... 颜色调色板[0]是RGBA全零。 调色板1 具有RGBA值255, 255, 255, 0
我最终会涉及多种其他深度格式,只是想从最简单的开始。
第二部分。如果有任何关于处理其他深度格式的指导,尤其是关于 alpha 通道(我已经在调色板中寻找)可能会使我困扰的特殊情况,请提供帮助。

enter image description here


1
如果你想完全理解IDAT格式,只需阅读标准,它非常简单:http://www.libpng.org/pub/png/spec/iso/index-object.html#11IDAT - leonbloy
1
谢谢提供那份额外的文档...我也会查看它,但是下面这篇文章实际上为我澄清了一些规范中我没有理解的内容。图形并不是我的主要领域,因此我正在尝试学习而不仅仅是“这里...用这个。” - DRapp
1个回答

7

如果你使用libpng会更容易,所以我猜这是为了学习目的。

问题是,如果你直接解压缩IDAT块,你会得到一些不应该被显示和/或可能需要被转换(因为应用了过滤器)才能得到实际的字节。在PNG格式中,每行都以一个额外的字节开头,告诉你对该行应用了哪个过滤器,其余字节包含行像素。

顺便说一下,00 20 00 40 00 80只有6个字节(不是你想象中的12个)。现在,如果你将这些数据视为二进制,你的3行将如下所示:

00000000 00100000
00000000 01000000
00000000 10000000

现在,你的图像每个像素是1位,所以需要1个字节来保存3个像素的一行。实际上使用了3个最高位(忽略了5个较低位)。我用x替换了被忽略的位,所以我认为更容易看到实际的像素0是黑色,1是白色):

00000000 001xxxxx
00000000 010xxxxx
00000000 100xxxxx

在这种情况下,没有对任何行应用过滤器,因为每行的第一个字节都是零(0表示未应用过滤器,值从14表示应用了过滤器)。


阅读 libpng 上的规范文件格式是必须的。其他位深度不是问题——尽管颜色和透明度有很多组合,但它们被定义得非常好。另一方面,过滤需要一些时间才能做到正确 :-) 不过,如果你掌握了这个,你也可以轻松地加入Adam-7交错。自己完成所有这些确实是一个很好的学习过程——PNG对我来说已经没有秘密了! - Jongware
1
感谢您对libpng的澄清和指导。是的,这更多是为了学习体验。我喜欢了解更多底层原理,而不仅仅是“只使用此”。我相信这有助于我在处理其他事情时,能够将类似的原则应用到我通常处理的其他工作中。 - DRapp
@DRapp:要查看真实世界的示例,请参阅我的pngdefry实用程序的源代码,以了解我对PNG进行钝化自上而下的处理方式--所有工作都在process函数中完成。整个过程都是在我的浏览器屏幕上打开官方规格书编写的。 - Jongware

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接