JPEG重启标记

10

我制作了JPEG解码器,但没有实现重启标记逻辑。这就是为什么我的程序无法处理一些图片的原因(例如使用PhotoShop保存的图像:文件->另存为->jpeg)。我想要实现重启标记逻辑,但是没有详细的在线说明重启标记逻辑如何工作。请问有人能告诉我更多关于重启标记,或者建议我可以阅读更多相关在线资源。谢谢!

1个回答

25

重新启动标记相当简单。它们设计用于在出现错误后允许重新同步。由于大多数JPEG图像是通过无误差的信道传输的,因此很少需要它们。使用FFDD标记定义了重启间隔为2字节数字。这告诉了重启标记之间有多少个MCU。当你遇到一个重启标记(FFD0-FFD7),将DC值(Y、Cr、Cb)重置为0,然后在一个字节边界上开始比特流(在FFDx之后)。解码图像时只需反复计数重启间隔即可。重启标记值将从FFD0递增到FFD7,然后再次从FFD0开始。标记值本身并不是非常重要,但它可以指示是否缺少大块数据。以下是我在解码器中的示例。我在我的比特流读取器中丢弃了重启标记。

iRestartCount = iRestartInterval;
for (y=0; y<Height_in_MCUs; y++)
   {
   for (x=0; x<Width_in_MCUs; x++)
       {
       <decode an MCU>
       if (iRestartInterval) // if there is a restart interval defined
          {
          if (--iRestartCount == 0)
             {
             iRestartCount = iRestartInterval; // reset restart inverval counter
             iDCPred0 = iDCPred1 = iDCPred2 = 0; // reset DC predictors
             if (*iBit & 7) // adjust bitstream to start on the next byte boundary
                {
                *iBit += (8 - (*iBit & 7));
                }
             } // if restart interval expired
          } // if restart interval defined
       } // for x
    } // for y

更新:现在重新启动标记有了新的作用——允许多线程JPEG编码器和解码器。由于每个MCU的“条带”在每个重新启动间隔开始时都会重置其DC值并且以字节边界开始,因此每个重新启动间隔可以由不同的线程独立编码或解码。编码器现在可以任意地将任务划分为N个线程,然后使用重新启动标记将数据“粘合”在一起。对于解码器来说,情况并不那么容易。如果存在重新启动标记,则可以将每个间隔分配给不同的线程。如果不存在,则仍然可以进行一些预解码技巧以将作业拆分为多个线程。


请问您能否告诉我更多的实现细节和逻辑? - MrD
如果它是一张具有交错的多组分图像,该怎么办? - adikshit
据我所见,无论配置如何,重启间隔都是指MCU(最小编码单元)。对于一个三分量彩色图像(Y/Cb/Cr),重启间隔是指3个DCT块的组。例如,间隔为100意味着300个DCT块(100个MCUs)。 - BitBank
@afuna 重启间隔是一个字值,因为每个图像的MCU大小都是固定的,所以它并不神秘。重启标记是一个单字节,具有模8值,指示序列号,以便可以检测数据丢失。 - BitBank
1
哎呀,你说的关于值是MCU数量的确是对的。然而,尽管MCU的尺寸是固定的(即8x8块等),但编码后的位数(经过游程编码和霍夫曼编码后)仍然因块而异,所以解码器如何知道从哪里开始(除非你的意思是先解码整个流,然后并行进行IDCT)。 - Reinstate Monica
1
@afuna 当然,对于可变长度编码数据,你不知道每个MCU的确切字节偏移量,但是因为所有标记字节都以FF开头,所以快速轻松地扫描前进以找到它们。 - BitBank

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