第 3 页 JPEG 简易文档 V2.14 [3]

来源:互联网 发布:淘宝推广网站 编辑:程序博客网 时间:2024/03/28 18:23
 

 二、解码过程简述

 8. 一个数据单元 Y 的解码 (其余类同)

在整个图片解码的开始, 你需要先初始化 DC 值为 0.

1) 先解码 DC:
         a) 取得一个 Huffman 码 (使用 Huffman DC 表)
         b) Huffman解码, 看看后面的数据位数 N
         c) 取得 N 位, 计算 Diff 值
         d) DC + = Diff
         e) 写入 DC 值:      " vector[0]=DC "

2) 解码 63 个 AC:

------- 循环处理每个 AC 直到 EOB 或者处理到 64 个 AC

       a) 取得一个 Huffman 码 (使用 Huffman AC 表)
       b) Huffman 解码, 得到 (前面 0 数量, 组号)
[记住: 如果是(0,0) 就是 EOB 了]

       c) 取得 N 位(组号) 计算 AC
       d) 写入相应数量的 0
       e) 接下来写入 AC

下一步的解码:

上一步我们得到了 64 个矢量. 下面我们还需要做一些解码工作:

1) 反量化 64 个矢量 : "for (i=0;i<=63;i++) vector[i]*=quant[i]" (注意防止溢出)
2) 重排列 64 个矢量到 8x8 的块中
3) 对 8x8 的块作 IDCT

对 8x8 块的 (Y,Cb,Cr) 重复上面的操作 [Huffman 解码, 步骤 1), 2), 3)]

4) 将所有的 8bit 数加上 128
5) 转换 YCbCr 到 RGB

9. JPG 文件(Byte 级)里怎样组织图片信息

注意 JPEG/JFIF 文件格式使用 Motorola 格式, 而不是 Intel 格式, 就是说, 如果是一个字的话, 高字节在前, 低字节在后.

JPG 文件是由一个个段 (segments) 构成的. 每个段长度 <=65535. 每个段从一个标记字开始. 标记字都是0xff 打头的, 以非 0 字节和 0xFF 结束. 例如 'FFDA' , 'FFC4', 'FFC0'. 每个标记有它特定意义,这是由第2字节指明的. 例如, SOS (Start Of Scan = 'FFDA') 指明了你应该开始解码. 另一个标记 DQT(Define QuantizationTable = 0xFFDB) 就是说它后面有 64 字节的 quantization 表

在处理 JPG 文件时, 如果你碰到一个 0xFF, 而它后面的字节不是 0, 并且这个字节没有意义. 那么你遇到的 0xFF字节必须被忽略. (一些 JPG 里, 常用用 0xFF 做某些填充用途) 如果你在做 huffman 编码时碰巧产生了一个 0xFF,那么就用 0xFF0x00 代替. 就是说在 jpeg 图形解码时碰到 FF00 就把它当作 FF 处理.

另外在 huffman 编码区域结束时, 碰到几个 bit 没有用的时候, 应该用 1 去填充.然后后面跟 FF.

下面是几个重要的标记:

SOI = Start Of Image = 'FFD8'
这个标记只在文件开始出现一次
EOI = End Of Image = 'FFD9'
JPG 文件都以 FFD9 结束

RSTi = FFDi ( i =  0..7)  [ RST0 = FFD0, RST7=FFD7]
     = 复位标记

通常穿插在数据流里, 我想是担心 JPG 解码出问题吧(应该配合 DRI 使用). RST 将Huffman 的解码数据流复位. DC 也重新从 0 开始计

(SOS --- RST0 --- RST1 -- RST2 --...
 ...-- RST6 --- RST7 -- RST0 --...)

10. 标记

下面是必须处理的标记

SOF0 = Start Of Frame 0 = FFC0
SOS  = Start Of Scan    = FFDA
APP0 = it's the marker used to identify a JPG file which uses the JFIF
    specification       = FFE0
COM  = Comment          = FFFE
DNL  = Define Number of Lines    = FFDC
DRI  = Define Restart Interval   = FFDD
DQT  = Define Quantization Table = FFDB
DHT  = Define Huffman Table      = FFC4

11. JPG 文件中 Haffman 表的储存

JPEG 里定义了一张表来描述 Haffman 树. 定义在 DHT 标记后面. 注意: Haffman 代码的长度限制在 16bit 内.

一般一个 JPG 文件里会有 2 类 Haffman 表: 一个用于 DC 一个用于 AC (实际有 4个表, 亮度的 DC,AC 两个, 色度的 DC,AC 两个)

这张表是这样保存的:
1) 16 字节:
第 i 字节表示了 i 位长的 Huffman 代码的个数 (i= 1 到 16)

2) 这表的长度 (字节数) = 这 16 个数字之和
现在你可以想象这张表怎么存放的吧? 对应字节就是对应 Haffman 代码等价数字. 我
不多解释, 这需要你先了解 Canonical Huffman Code. 这里只举一个例子:

Haffman 表的表头是 0,2,3,1,1,1,0,1,0,0,0,0,0,0,0,0
就是说长度为 1 的代码没有
长度为 2 的代码为 00
                 01
长度为 3 的代码是 100
                 101
                 110
长度为 4 的代码是 1110
长度为 5 的代码是 11110
长度为 6 的代码是 111110
长度为 7 的代码没有 (如果有一个的话应该是 1111110)
长度为 8 的代码是 11111100
         .....
后面都没有了.

如果表下面的数据是
    45 57 29 17 23 25 34 28

就是说
    45 = 00
    57 = 01
    29 = 100
    17 = 101
    23 = 110
等等...

使用 Canonical Huffman Code 的好处在于可以很简洁的重建对应关系表.

12. 采样系数

下面讲解的都是真彩 JPG 的解码, 灰度 JPG 的解码很简单, 因为图形中只有亮度信息. 而彩色图形由 (Y, Cr, Cb)构成, 前面提到过, Y 通常是每点采样一次, 而 Cr,Cb 一般是 2x2 点采样一次, 当然也有的 JPG 是逐点采样, 或者每两点采样(横向两点, 纵向一点) 采样系数均被定义成对比最高采样系数的相对值.

一般情况 (即: Y 逐点采样, Cr Cb 每 2x2 点一次) 下: Y 有最高的采样率, 横向采样系数HY=2 纵向采样系数 VY=2; Cb 的横向采样系数 HCb=1, 纵向采样系数 VCb=1;同样 HCr=1, VCr=1

在 Jpeg 里, 8x8 个原始数据, 经过 RLE, Huffman 编码后的一串数据流称为一个
Data Unit (DU) JPG 里按 DU 为单位的编码次序如下:

     1)      for  (counter_y=1;counter_y<=VY;counter_y++)
                  for (counter_x=1;counter_x<=HY;counter_x++)
                     {  对 Y 的 Data Unit 编码 }

     2)      for  (counter_y=1;counter_y<=VCb ;counter_y++)
                  for (counter_x=1;counter_x<=HCb;counter_x++)
                     {  对 Cb 的 Data Unit 编码 }

     3)      for  (counter_y=1;counter_y<=VCr;counter_y++)
                  for (counter_x=1;counter_x<=HCr;counter_x++)
                     {  对 Cr 的 Data Unit 编码 }

按我上面的例子: (HY=2, VY=2 ; HCb=VCb =1, HCr,VCr=1) 就是这样一个次序
    YDU,YDU,YDU,YDU,CbDU,CrDU
这些就描述了一块 16x16 的图形. 16x16 = (Hmax*8 x Vmax*8) 这里 Hmax=HY=2 Vmax=VY=2

一个 (Hmax*8,Vmax*8) 的块被称作 MCU (Minimun Coded Unix) 前面例子中一个
MCU = YDU,YDU,YDU,YDU,CbDU,CrDU

如果  HY =1, VY=1
      HCb=1, VCb=1
      HCr=1, VCr=1
这样 (Hmax=1,Vmax=1), MCU 只有 8x8 大, MCU = YDU,CbDU,CrDU

对于灰度 JPG, MCU 只有一个 DU (MCU = YDU)

JPG 文件里, 图象的每个组成部分的采样系数定义在 SOF0 (FFC0) 标记后

13. 简单说一下 JPG 文件的解码

解码程序先从 JPG 文件中读出采样系数, 这样就知道了 MCU 的大小, 算出整个图象
有几个 MCU. 解码程序再循环逐个对 MCU 解码, 一直到检查到 EOI 标记. 对于每个
MCU, 按正规的次序解出每个 DU, 然后组合, 转换成 (R,G,B) 就 OK 了

出处:云风工作室
责任编辑:moby

原创粉丝点击