二、解码过程简述 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 了