我有一个C ++应用程序,它非常直接地要求从JPEG文件中提取一些元数据。
有各种各样的库可以做到这一点,但最初在原型设计时我只是想快速完成工作,因为我知道JPEG文件的解剖结构很方便地由a series of markers描绘,(即{{1}具有相应长度字段的元组),我认为通过从第一个标记开始迭代JPEG文件的各部分并从标记迭代到标记直到我点击图像结束标记是很容易的。
这很容易实现,只需将JPEG数据读入{0xFF, 0xXX}
,然后迭代它,找到标记部分。我最终将这个逻辑抽象为一个“标记 - 迭代器”类,使其更容易使用。
一般来说这很有效。实际上,通常我感兴趣的元数据出现在SOI标记之后的第一个标记中(即APP0标记,以std::vector<unsigned char>
开头)。因此,在大多数情况下,我甚至不需要实际编写逻辑来迭代整个 JPEG文件 - 我只需检查始终包含APP0标记的标题。
除此之外,我发现我的假设是错误的。显然,{ 0xF0, 0xE0 }
,0xF0
标记doesn't ALWAYS have to be the first segment。
好的,没问题 - 无论如何,迭代所有标记都很容易。除此之外,我遇到了另一个问题。在大多数情况下,找到下一个标记就像将长度字段添加到当前索引位置到JPEG数据缓冲区一样简单。但显然某些长度字段实际上并不表示特定段的整个长度。例如,JPEG文件中的“扫描开始”段后跟"entropy-coded data"。 “熵编码数据”的大小不包括在长度字段中。
所以...如果你在迭代JPEG文件时点击“扫描开始”标记,你怎么知道下一个标记的开始位置?您是否只需逐字节进行线性搜索即可找到下一个0xE0
字符?
实际上,这也不起作用,因为熵编码数据本身可能包含0xFF
个字符。但是,显然JPEG标准要求熵编码数据中出现的任何0xFF
字节后面必须跟0xFF
字节,以区别于实际标记。
好的,所以在没有进行强力线性搜索的情况下,在“扫描开始”部分之后仍然没有找到任何方法来找到下一个标记。这是唯一可行的方法(没有特定于“扫描开始”部分的复杂解析逻辑吗?)
答案 0 :(得分:0)
也许访问http://www.ijg.org/,下载C代码并检查它们在lib上的作用?
我认为djpeg.c有一个标记解析器。
答案 1 :(得分:0)
所以......如果你点击了#34;开始扫描&#34;迭代JPEG时的标记 文件,你怎么知道下一个标记的开始位置?你有没有 逐字节进行线性搜索,找到下一个0xFF字符?
在扫描中,您可以使用FF00或重启标记。任何其他FFxx序列应该是下一个块的开始。
此外,JPEG图像不必具有APP0标记。