【问题标题】:Pseudocode: How to decode a PNG file from bits and bytes?伪代码:如何从位和字节解码 PNG 文件?
【发布时间】:2018-11-11 07:07:49
【问题描述】:

我一直试图通过对我在 GIMP 中创建的 .png 文件进行逆向工程来解决这个问题。它是 4x4 像素。我的目标是从文件中解码出原始像素,以便将其反转为编码。

这是文件的完整十六进制转储:

89504E47 0D0A1A0A 0000000D 49484452 00000004 00000004  
08020000 00269309 29000000 3F494441 54081D01 3400CBFF  
01CC96B1 134FE120 C0CECDF1 5101FFA5 60000000 000000E0  
403201DF E59286DF 6D000000 00000004 EDB11F00 2E007A21  
93EDB11F 3063136F 4733525A 00000000 49454E44 AE426082  

根据spec,我们从前8个字节的PNG签名开始。

89504E47 0D0A1A0A

然后我们有重复的“块”结构,这个文件有 3 个“块”、标题 (IHDR)、图像数据 (IDAT) 和结尾的“块” (IEND)。

每个chunk被排列成:前4个字节为chunk数据长度,后4个字节为数据类型,n字节为实际数据,4个字节为循环冗余校验(CRC ) 的数据类型和实际数据部分。

接下来……

0000000D

是块的数据长度(13 字节)。

49484452

是块的类型(IHDR)。

00000004 00000004 08020000 00

是块的数据(4字节宽,高;1字节位深,颜色类型,压缩方式,过滤方式,隔行方式)。

269309 29

是数据和类型的CRC(设法从here得到代码来解决这个问题。

000000 3F

是下一个块的数据长度(63 字节)。

494441 54

是块的类型 (IDAT)。

081D01 3400CBFF 01CC96B1 134FE120 C0CECDF1 5101FFA5 60000000 000000E0 403201DF E59286DF 6D000000 00000004 EDB11F00 2E007A21 936F 3061>

是块的实际数据(经过压缩和过滤的图像数据)。

所以我的实际问题是如何将最后一部分解码为原始像素?

根据spec,我必须首先解压缩数据(INFLATE?),然后对其进行过滤(??)以留下像素扫描线(我的目标)。

如果这可以用伪代码来解释,那就太棒了!否则我对 Swift 很熟悉,而对 C 则不太熟悉...

【问题讨论】:

  • 我知道您想严格执行此操作以应对挑战,否则您应该使用预先存在的库。
  • 您确定要实现 zlib 组件,还是可以使用库进行解压和/或过滤? zlib 的伪代码并不小,部分原因是需要考虑变体。
  • 我更喜欢实现zlib;拜访图书馆并不能真正教会我任何东西。如果不是伪代码,只是分解成更简单的步骤,我可以自己研究?
  • 如果我在哪里,我会从 GIF ... as it is well documented 开始,并提供示例(请参阅其中的 3MF 链接)并包含非常相似的压缩算法。完成后移至png。另一种可能性是使用 zlib 并在工作时用您自己的代码一个一个地替换 zlib 调用。遗憾的是我自己没有做 PNG 解码器/编码器(我使用 pngDelphi),所以无法提供更多详细信息,但我确实做了PCX,GIF,DDS,SGI,SVG,EMF,WMF 和更多的解码器/编码器过去(因为我需要他们)
  • 无论如何,你应该添加一些代码以及你到底卡在哪里,这样这个有趣的问题就不会因为太宽泛或离题而被关闭....

标签: image algorithm bitmap png pseudocode


【解决方案1】:

我认为pngcheck会对你有很大帮助:

pngcheck -vv result.png

样本输出

File: result.png (334985 bytes)
  chunk IHDR at offset 0x0000c, length 13
    600 x 450 image, 24-bit RGB, non-interlaced
  chunk IDAT at offset 0x00025, length 65536
    zlib: deflated, 32K window, default compression
    row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
      1 4 4 4 4 4 4 4 1 4 4 4 4 4 4 4 1 4 4 4 4 4 4 4 4
      1 4 4 1 4 1 4 1 4 4 4 4 4 4 1 1 1 1 1 1 1 1 1 1 1
      1 1 1 1 1 1 1 1 1 4 4 1 1 1 1 1 1 1 4 4 1 4 1 1 4
      4 4 4 4 4 1 4 4 4 4 4 4 4 1 4 4 4 4 4 4 4 (96 out of 450)
  chunk IDAT at offset 0x10031, length 65536
    row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
      1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1
      4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
      4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 4 4
      4 4 4 4 4 4 4 4 4 4 4 4 4 1 4 4 4 (188 out of 450)
  chunk IDAT at offset 0x2003d, length 65536
    row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
      4 4 4 4 4 4 4 4 4 4 4 4 1 4 4 4 4 4 4 4 4 4 4 4 4
      4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
      4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
      4 1 4 4 4 4 4 4 4 4 (273 out of 450)
  chunk IDAT at offset 0x30049, length 65536
    row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
      4 4 4 4 4 4 4 4 4 2 4 4 4 4 4 1 4 4 4 4 4 4 4 4 4
      4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
      4 4 4 4 4 4 4 4 4 4 4 4 4 1 4 4 4 4 4 4 4 1 4 4 4
      4 4 4 4 1 4 4 4 (356 out of 450)
  chunk IDAT at offset 0x40055, length 65536
    row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
      4 4 4 4 1 4 4 4 4 4 4 4 1 4 4 4 4 4 4 4 4 4 4 4 4
      4 4 4 1 4 4 4 4 4 4 4 1 1 1 4 4 1 4 4 1 1 1 4 4 4
      4 4 1 1 1 4 1 4 4 4 1 4 1 4 4 4 1 4 1 4 4 4 4 4 4
      4 1 1 4 1 4 4 1 4 1 (441 out of 450)
  chunk IDAT at offset 0x50061, length 7188
    row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
      4 1 1 4 4 4 4 1 4 (450 out of 450)
  chunk IEND at offset 0x51c81, length 0
No errors detected in result.png (8 chunks, 58.6% compression).

【讨论】:

  • File: understand.png (120 bytes) chunk IHDR at offset 0x0000c, length 13 4 x 4 image, 24-bit RGB, non-interlaced chunk IDAT at offset 0x00025, length 63 zlib: deflated, 256-byte window, superfast compression row filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth): 1 1 1 4 (4 out of 4) chunk IEND at offset 0x00070, length 0 No errors detected in understand.png (3 chunks, -150.0% compression).
【解决方案2】:

你的问题对于伪代码来说太宽泛了——或者至少是可操作的伪代码——如果我们足够高,你已经知道了基础知识:1. uncompress, 2. unfilter, 3. profit。

由于您在 cmets 中声明您想自己做所有事情,我建议您从实现默认解压算法 ZLIB CM=8 "deflate" 开始,这在 https://www.ietf.org/rfc/rfc1951.txt 等中有很好的描述。

【讨论】:

    【解决方案3】:

    本书为程序员讲解解码过程:

    https://www.amazon.com/Compressed-Image-File-Formats-JPEG/dp/0201604434

    整个过程非常复杂,以适应 SO 答案的空间。 PNG 使用两种不同的压缩方法:LZ 和 Huffman 编码。

    【讨论】:

    • 本书一步一步解释了如何进行PNG解码。
    猜你喜欢
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    • 2021-08-29
    • 2016-06-13
    • 2011-04-11
    相关资源
    最近更新 更多