【问题标题】:Parsing JPEG SOS Marker解析 JPEG SOS 标记
【发布时间】:2014-11-03 13:47:27
【问题描述】:

有一个question with the same title,但不幸的是它对我没有帮助。

我正在尝试解析 SOS 标记的数据。我能找到的所有文档都说,在标记 (0xFFDA) 之后是一个两个字节的数字,它定义了这个段的长度——for example here——就像大多数可变大小的标记一样。但在这种情况下,我似乎没有正确理解它。它适用于所有其他标记类型。

我检查了多个文件,但无法正确处理。这个数字是否没有定义完整的 SOS 字段有多长?因此,对于基线 JPEG,应该有一个 SOS 段,之后应该是图像结束标记。如果它是渐进式的,则可以有多个 SOS 段,但仍然都应该有一个长度字段。

我有一张带有SOF0 标记的图片,所以它应该是基线。我相信这是正确的SOFn 标记,因为可以在该标记之后找到图像分辨率。使用十六进制编辑器,我找到了 3 个 0xFFDA 标记,并且它们在接下来的 2 个字节中都有 0x000C。因此,据我了解,该段应始终为 12 字节长。但是在所有 3 种情况下,在 12 个字节的数据之后都没有新的标记。我猜最后一个是我正在寻找的扫描,因为如果出现0xFF 值,则后面跟着0x00——除了重置标记。

0xFFDA 后面的那两个字节不是长度字段吗?

编辑: 因此,多亏了 cmets 和 answer,实际压缩数据似乎没有长度字段,知道它在哪里结束的唯一方法似乎是对其进行解码。

为什么基线 DCT 图像需要多次扫描?我会理解为什么它有两个;主图像和缩略图,但第三次扫描是什么?

但还有一件事。根据 DRI Marker (Define Restart Interval),它包含一个 Scan 应该有一个重新启动标记 0xFFD0 - 0xFFD7 之后的值。但我似乎也误解了这一点,或者我做得不对。例如,标记包含值0x0140 作为重新启动间隔。在下面的扫描中,我从头开始搜索第一个 0xFFD0,但它出现在 862 字节而不是 320 字节之后。

【问题讨论】:

  • FFDA 后面的 2 个字节是长度 (12),但紧跟在 SOS 标记之后的是压缩的图像数据。您需要对数据的“扫描”进行解码,下一个 FFxx 标记将位于压缩数据之后。
  • @BitBank,所以没有字段告诉我压缩数据有多长?
  • 压缩后的数据没有长度字段;必须对其进行解码才能找到结尾,或者如果您必须知道结尾在哪里,请在 FFDA 之后查找下一个 FFD9 标记。
  • @BitBank,我已经编辑了我的问题,也许你可以再帮忙一次。
  • 基线图像将进行一次扫描。带有缩略图的文件实际上是 2 个 JPEG 图像和 2 个扫描。请发布具有 3 次扫描的示例图像,我会看看。这是我之前关于重启标记的回答:stackoverflow.com/questions/8748671/…

标签: jpeg file-format


【解决方案1】:

SOS 标记包含压缩数据; JPEG 流中最复杂的部分。 SOFn 标记指示数据的格式。 SOF0 和 SOF1 的处理方式相同。 SOF2(渐进式)有很大不同。 (SOFn 标记的读取不常用或不普遍支持)。

长度是 SOS 标头的长度,而不是压缩数据的长度。大部分标头仅适用于逐行扫描(SOF2)。

压缩后的数据跟在头部之后。压缩数据没有长度。您必须扫描数据才能找到下一个标记。

【讨论】:

  • 您无需解码数据即可找到 SOF 标记的结尾。扫描流中的 FF。 FFFF 表示压缩的 FF 值(跳过那些)。 FFD0 - FFD7 是重新启动标记。忽略那些。任何其他 FFxx 值都应该是流中的下一个块。除非您解压缩,否则重新启动标记没有任何意义。它们是 MCU 间隔,而不是字节间隔。
  • 由于某些原因这是不正确的,因为可以将 FF 创建为值和沿。因此,如果您正在使用它,您必须检查更多信息。
  • 我有一个错误。 FF 编码为 FF00。除了重启标记之外,这就是您需要检查的所有内容。
  • 取决于你真正谈论的立场。基本上你只需要添加更多的检查,然后只是 FF+一些。你所能做的就是降低你将某事解释为不是开始的可能性。所以基本上应该适应它,否则它会在应用程序的上层(解码器代码的用户)中产生难以发现的随机缺陷。
  • @MartinKersten,我相信 user3344003 是对的。来自维基百科page在熵编码的数据中,在任何 0xFF 字节之后,编码器会在下一个字节之前插入一个 0x00 字节,因此似乎没有任何不打算使用的标记,从而防止构图错误。解码器必须跳过这个 0x00 字节。这种技术称为字节填充(参见 JPEG 规范第 F.1.2.3 节)
【解决方案2】:

如何在 SOS 标记 (0xFFDA) 之后找到下一个标记的总结

  1. 跳过 SOS 标记后的前 3 个字节(2 个字节的标头大小 + 1 个字节的扫描图像组件数)。
  2. 搜索下一个FFxx 标记(跳过每个FF00,范围从FFD0FFD7,因为它们是扫描的一部分)。

*这是来自https://www.w3.org/Graphics/JPEG/itu-t81.pdf的user3344003 +我的知识+表B.1的帖子下方的cmets摘要。

*基于表 B.1,我还可以怀疑值 FF01FF02FFBF 也应该在第 2 点被跳过,但我不确定它们是否不能作为编码 SOS 数据的一部分出现。


以上其他问题:

为什么基线 DCT 图像需要多次扫描?我会理解为什么它有两个;主图像和缩略图,但第三次扫描是什么?

如果图像流包含 APP2 标记 (0xFFE2),这告诉我们它可以是(但不一定是)Multi Picture JPEG(名为 MPF 的标签),我们可以有超过 3 张图像。一般来说,APP标记可以存储任何东西,JPEG文件中有很多与APP片段相关的标准。

第一个表告诉我们每个 APP 段中可以存储的“事物”:https://sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html

【讨论】:

  • 没有给出答案。它实际上取决于 JPEG 容器使用的实际压缩。原ITU T.81说在编码过程中我们要用0xFF 0x00字节序列转义0xFF字节,解码过程中我们应该跳过0xFF 0x00字节序列中的0x00。而其他 JPEG 标准扩展并不完全遵循本指南。例如,ITU T.87 JPEG-LS 编码样本在原始标准文档提供的样本 .jls 文件中显然有 0xFF,而不是 0x00(例如 0xFF 0x7F)。这是标准或标准示例的失败,还是只是编写标准的人?
猜你喜欢
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-01
  • 1970-01-01
  • 2019-05-05
相关资源
最近更新 更多