从jpeg文件生成AC元素

时间:2011-12-19 19:28:32

标签: jpeg huffman-code

我正在解码jpeg文件。我已经生成了霍夫曼表和量化表,我已经达到了解码DC和AC元素的程度。例如,假设我有下一个数据

FFDA 00 0C 03 01 00 02 11 03 11 00 3F 00 F2 A6 2A FD 54 C5 5F FFD9

如果我们忽略来自SOS标记的少量字节,我的实际数据从F2字节开始。所以我们用二进制(从F2字节开始)写它:

1111 0010 1010 0110 0010 1010 1111 1101 0101 0100 1100 0101 0101 1111
  F    2    A    6   2     A    F    D    5    4    C    5    5   F

解码时,第一个元素是亮度DC元素,所以让我们解码它。

[1111 0]010 1010 0110 0010 1010 1111 1101 0101 0100 1100 0101 0101 1111
  F    2    A    6   2     A    F    D    5    4    C    5    5   F

所以11110是元素08的霍夫曼代码(在我的例子中)。这意味着接下来的8位是我的DC值。当我接下来的8位时,值为:

1111 0[010 1010 0]110 0010 1010 1111 1101 0101 0100 1100 0101 0101 1111
  F    2    A    6   2     A    F    D    5    4    C    5    5   F

DC元素值为-171。

这是我的问题:接下来是亮度AC值,但是当AC非零时,我真的不明白标准吗? TNX!

1 个答案:

答案 0 :(得分:4)

如您所见,DC值定义为指定正或负DC值的“额外”位数。 AC系数被不同地编码,因为它们中的大多数是0.霍夫曼表定义了具有“跳过”值和“额外位”长度的AC系数的每个条目。跳过值是在存储值之前要跳过的AC系数的数量,并且额外的比特被处理为与DC值相同的方式。解码AC系数时,可以解码1到63之间的值,但MCU结束的编码方式可能会有所不同。您可以将实际值存储在索引63处,如果您处于索引> 48,你可以获得一个ZRL(零游程长度= 16个零),或任何超过结束的组合。简化的解码循环:

void DecodeMCU(signed short *MCU)
{
int index;
unsigned short code, skip, extra;

   MCU[0] = decodeDC();
   index = 1;
   while (index < 64)
   {
      code = decodeAC();
      skip = code >> 4; // skip value
      extra = code & 0xf; // extra bits
      index += skip;
      MCU[index++] = calcACValue(extra);
   }
}

颜色分量可以交错(典型)或存储在单独的扫描中。元素在每个MCU中以Z字形顺序编码(首先是低频元素)。定义MCU的8x8系数块的数量根据颜色子采样而变化。对于1:1,将有1个Y,然后是1个Cr和1个Cb。对于典型的数码相机图像,水平轴是二次采样的,因此您将获得2个Y块,然后是1 Cr和1 Cb。压缩图像的质量设置确定所使用的量化表以及编码多少个零AC系数。质量越低,每个MCU的零越多。当您在MCU上执行反向DCT时,零的数量将决定8x8,16x8,8x16或16x16像素块中保留多少细节。以下是基本步骤:

1)熵解码8x8系数块,每个颜色分量分别存储 2)对系数进行去锯齿和去量化 3)对系数执行逆DCT(可能是6 8x8块,用于4:2:0子采样)
4)将颜色空间从YCrCb转换为RGB或任何你需要的颜色