Sil*_*ler 5 c++ algorithm jpeg file-format
我有一个 C++ 应用程序,它有一个非常简单的要求,即从 JPEG 文件中提取一些元数据。
有各种库可以做到这一点,但最初在原型设计时我只是想快速完成工作,因为我知道 JPEG 文件的结构很方便地由一系列标记(即{0xFF, 0xXX}具有相应长度字段的元组)来描述,我认为通过从第一个标记开始迭代 JPEG 文件的各个部分,并从一个标记迭代到另一个标记,直到我点击图像结束标记,这很容易。
这很容易实现,只需将 JPEG 数据读入std::vector<unsigned char>,然后对其进行迭代,找到标记部分。我最终将此逻辑抽象为一个“标记迭代器”类,使其更易于使用。
通常这很好用。事实上,通常我感兴趣的元数据出现在 SOI 标记之后的第一个标记中(即 APP0 标记,以 开头{ 0xF0, 0xE0 })。因此,在大多数情况下,我什至不需要实际编写逻辑来迭代整个JPEG 文件 - 我只需检查始终包含 APP0 标记的标题。
直到那时我才发现我的假设是错误的。显然,0xF0,0xE0标记并不总是必须是第一段。
好的,没问题 - 无论如何迭代所有标记都很容易。除了,然后我遇到了另一个问题。在大多数情况下,找到下一个标记就像在 JPEG 数据缓冲区的当前索引位置添加一个长度字段一样简单。但显然某些长度字段实际上并不表示特定段的整个长度。例如,JPEG 文件中的“扫描开始”段后跟“熵编码数据”。“熵编码数据”的大小不包括在长度字段中。
所以……如果您在遍历 JPEG 文件时遇到“扫描开始”标记,您怎么知道下一个标记从哪里开始?您是否只需要逐字节进行线性搜索才能找到下一个0xFF字符?
实际上,这也行不通,因为熵编码的数据本身可能包含0xFF字符。然而,显然 JPEG 标准要求0xFF出现在熵编码数据中的任何字节都必须跟一个0x00字节,以将其与实际标记区分开来。
好的,所以如果不进行蛮力线性搜索,我仍然无法找到“扫描开始”部分之后的下一个标记。这是唯一可能的方法吗(没有特定于“扫描开始”部分的复杂解析逻辑?)