【发布时间】:2015-11-05 01:57:23
【问题描述】:
我对这个问题(见:底部)的希望是尽可能多地列出我对放气过程的了解,并且我可以在我(可能非常)被误导的地方得到更正。希望最后,这个问题可以成为一个方便的资源。
Zlib 头文件
前两个字节相当于 zlib 压缩的标头,格式为 (credit)
---CMF--- ---FLG---
0111.1000 1101.0101
CINF -CM- +-||
| |+- FCHECK
| +-- FDICT
+---- FLEVEL
从RFC 1950,从右到左:
FCHECK (1.0101) - 验证 CMF 和 FLG 作为 16 位无符号整数是 31 的倍数
FDICT (0) - 如果设置,则表示预设 DICT 紧跟在 FLG 之后
FLEVEL (11) - 压缩“强度”[0-3]
CM (1000) - 用于压缩方法,其中 CM = 8 == "deflate" 压缩方法
CINF(0111) - 表示使用的滑动窗口的大小,其中CINF = 7 == 32K滑动窗口
数据块头
NEW BYTE 中接下来的三位相当于 Huffman 编码块的标头:
---CMF--- ---FLG--- NEW BYTE
0111.1000 1101.0101 11101100
|-|
| +- BFINAL
+--- BTYPE
从RFC 1951从右到左:
BFINAL (0) - 如果这是最后一个数据块,则设置为 (1)
BTYPE (10) - 霍夫曼编码:(00)none; (01)固定霍夫曼码; (10) 动态代码; (11) 无效
霍夫曼密码
从这里我将解决 BTYPE = (10) 的假设
以下值立即进行:
NEW BYTE NXT BYTE
(11101)100 -> 101)(11101) -> 0111111(1
|-|
| +- BFINAL
+--- BTYPE
HLIT(11101) - 5 位长度/文字代码,添加 257 (257-286)HDIST(11101) - 5 位距离代码,添加 1 (1-32)HCLEN(1111) - 4 位码长代码,添加 4 个 (4-19)
紧随其后的是HCLEN(别忘了+4)3位字段,其中值按顺序分配给此序列:
16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1 15
由于 HCLEN = 19,所以使用整个序列
该序列中的代码长度为0 表示未使用相应的符号。
作为一个图形示例,在读取 19x3 位后,我们有六个额外的位(括号中的额外位):
NXT BYTE 00000000 00000000 00000000 00000000 00000000 00000000 [000000](00
我的问题
上面括号中的最后几位会被扔掉吗?
【问题讨论】:
-
我不会投反对票,但我怀疑这个问题的价值。 1)这不是关于 PNG,而是关于 ZLIB/deflate 规范(PNG 使用 ZLIB/deflate 在这里无关紧要 - “解耦层”的概念对于工程来说是必不可少的)。 2)这不是一个真正的具体问题,而是使用一个特殊的例子来帮助理解 ZLIB/deflate 格式的细节(这对其他人几乎没有帮助)3)假装有点奇怪(尽管也许也值得称赞)了解位级别的 ZLIB 流,特别是如果您不了解 Huffman 压缩
-
... 并且在问题标题的上下文中闻起来很有趣:您通常不需要理解这么低级别的东西来理解 PNG 格式。 4) 看这里stackoverflow.com/questions/26018811/…
-
我想我理解这个领域的东西的定义是能够编码它。就像在程序中解码器一样。但我会争论这个问题的价值,真正掌握字节的文件 I/O 是一个很好的练习,甚至是单个位。它还涉及字节序。作为一名受过大学教育的 CS 学生,我在所有领域都很薄弱。可能题主写错了,能改吗?应该是,如果可以的话?我对包含 PNG 的(可能很糟糕)逻辑是,大量搜索 deflate 自然会涉及 PNG。我相信这是值得学习的好东西。
-
@leonbloy 另外,在我看来,堆栈溢出的最佳功能之一是真正深入的答案,可以消除任何混淆并提出执行 X 的最佳方法。我试图模仿或引起社区这样的回答
-
@MarcusJ 我最初做这一切是因为我正在研究 PNG 文件。 IDAT 块的结构与我在上面的布局完全相同。从 zlib 标头开始,然后是数据块标头,然后是霍夫曼代码,然后是编码数据。
0x78的第一个字节与我上面的示例相同(包含 CINF 和 CM 的 CMF 字节)
标签: c++ binary zlib huffman-code deflate