扫描JPEG文件的标记

5
我有一个C++应用程序,需要从JPEG文件中提取一些元数据。虽然有各种库可以完成这个任务,但最初在原型设计时,我只想快速完成任务。由于我知道JPEG文件的解剖结构是由一系列标记(即具有相应长度字段的{0xFF,0xXX}元组)方便地界定的,所以我认为只需从第一个标记开始迭代JPEG文件的部分,并从标记到标记迭代,直到遇到图像结束标记就足够容易了。
这个实现很容易,只需将JPEG数据读入一个std::vector<unsigned char>中,然后迭代查找标记部分。我最终将这个逻辑抽象成了一个"标记迭代器"类,使其更易于使用。

通常这个方法非常有效。事实上,我感兴趣的元数据通常出现在SOI标记后的第一个标记中(即APP0标记,以{ 0xF0, 0xE0 }开头)。因此,大部分时间我甚至不需要编写逻辑来迭代整个JPEG文件——我只需要检查头部,它始终包含APP0标记。

但是后来我发现我的假设是错误的。显然,0xF00xE0标记不总是第一个片段

好的,没问题 - 遍历所有标记很容易。但是,我遇到了另一个问题。大多数情况下,找到下一个标记就像在当前索引位置添加长度字段一样容易。但显然有些长度字段实际上并没有指示特定段的整个长度。例如,在JPEG文件中,“扫描开始”(Start-Of-Scan)段后面跟随着“熵编码数据”。 “熵编码数据”的大小未包含在长度字段中。
那么...如果您在迭代JPEG文件时遇到“扫描开始”标记,如何知道下一个标记从哪里开始?您只需进行逐字节的线性搜索以查找下一个0xFF字符吗?
实际上,这也行不通,因为熵编码数据本身可能包含0xFF字符。然而,显然根据JPEG标准,出现在熵编码数据中的任何0xFF字节都必须后跟一个0x00字节,以将其与实际标记区分开来。
好吧,这样仍然没有任何办法可以在“扫描开始”部分之后找到下一个标记,而不进行暴力线性搜索。这是唯一可能的方法吗(没有特定于“扫描开始”部分的复杂解析逻辑)?

你可以尝试从图像文件的开头和结尾搜索元数据,希望没有一个明智的软件会在文件中间将元数据夹杂在图像数据之间。 - Louis Ricci
所有元数据都应该在你触发SOS标签之前定义。 - BitBank
你可以使用 https://www.exiv2.org/ 提取元数据。 - Mihai8
2个回答

1
如果在遍历JPEG文件时遇到“开始扫描”标记,如何知道下一个标记从哪里开始?你只需要进行逐字节的线性搜索来查找下一个0xFF字符吗?
在扫描中,你可能会遇到FF00或重启标记。任何其他的FFxx序列都应该是下一个块的开始。
此外,JPEG图像不一定需要有APP0标记。

-1

或许可以访问http://www.ijg.org/,下载C代码并查看他们在库上的操作?

我认为djpeg.c有一个标记解析器。


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