一.实验原理
1.JPEG编码流程
编码流程图如下,解码是编码的逆过程。
图像预处理
将输入的图像分成若干个8×8的小块,需对图像的宽和高进行剪裁剪,使其都为8的倍数,不足的部分复制最近的像素的值。
目的:方便进行8×8 DCT变换。
零电平偏置
将所有像素的数值减去128,将其范围从[0,255]变成[-128,127]。
目的:使像素的绝对值出现3位10进制的概率大大减少。
8x8DCT变换
把每个单独的彩色图像分量图像分成8×8的图像块,再以8×8的图像块为单位进行量化和编码处理。
目的:实现能量集中和去相关,便于去除图像的空间冗余度。
量化
利用根据人眼视觉特性设计的量化矩阵进行量化。由于人眼对低频敏感,高频不敏感,所以采用低频细量化,高频粗量化。
目的:减少视觉冗余。
编码
(1)对直流系数编码——差分编码
直流系数 F(0,0)反映该子图像中包含的直流成分,具有数值大、相邻8×8图像块的DC系数值变化不大这两个特点。所以对 DC 系数采用差值脉冲编码(DPCM),即对本像素块直流系数与前一像素块直流系数的差值进行无损编码。
(2)对交流系数编码——游程编码
经DCT变换后,系数大多集中在左上角低频分量区,于是进行Z 字形扫描按频率的高低顺序读出的游程编码(RLC),并在最后加上块结束码(EOB)。然后对系数序列分组,将非零系数和它前面的相邻的全部零系数分在一组内,每组用两个符号表示:[(Run,Size),(Amplitude)]
其中Amplitude表示非零系数的幅度值,Run表示零的游程即零的个数,Size表示非零系数的幅度值的编码位数。
2.JPEG文件格式
(1)Segment的组织形式
JPEG 在文件中以 Segment 的形式组织,它具有以下特点:
- 均以 0xFF 开始,后跟 1 byte 的 Marker 和 2 byte 的 Segment length(包含表示
Length 本身所占用的 2 byte,不含“0xFF” + “Marker” 所占用的 2 byte); - 采用 Motorola 序(相对于 Intel 序),即保存时高位在前,低位在后;
- Data 部分中,0xFF 后若为 0x00,则跳过此字节不予处理;
(2)JPEG 的 Segment Marker
(3)具体信息
- SOI与EOI
SOI:Start of Image, 图像开始标记代码 2字节 固定值0xFFD8
EOI:End of Image, 图像结束标记代码 2字节 固定值0xFFD9 - APP0 应用程序保留标记0
标记代码 2字节 固定值0xFFE0
包含9个具体字段:
① 数据长度 2字节 ①~⑨9个字段的总长度
② 标识符 5字节 固定值0x4A46494600,即字符串“JFIF0”
③ 版本号 2字节 一般是0x0102,表示JFIF的版本号1.2
④ X和Y的密度单位 1字节 只有三个值可选(0:无单位;1:点数/英寸;2:点数/厘米 )
⑤ X方向像素密度 2字节 取值范围未知
⑥ Y方向像素密度 2字节 取值范围未知
⑦ 缩略图水平像素数目 1字节 取值范围未知
⑧ 缩略图垂直像素数目 1字节 取值范围未知
⑨ 缩略图RGB位图 长度可能是3的倍数 缩略图RGB位图数据 - DQT 定义量化表
标记代码 2字节 固定值0xFFDB
包含9个具体字段:
① 数据长度 2字节 字段①和多个字段②的总长度
② 量化表 数据长度-2字节
a) 精度及量化表ID
1/字节,其中高低4位具体如下
高4位:精度,只有两个可选值 (0:8位;1:16位 )
低4位:量化表ID,取值范围为0~3
b) 表项
(64×(精度+1))字节
例如8位精度的量化表,其表项长度为64×(0+1)=64字节
本标记段中,字段②可以重复出现,表示多个量化表,但最多只能出现4次 - SOF0 帧图像开始
标记代码 2字节 固定值0xFFC0
包含9个具体字段:
① 数据长度 2字节 ①~⑥六个字段的总长度
② 精度 1字节 每个数据样本的位数 通常是8位,一般软件都不支持 12位和16位
③ 图像高度 2字节 图像高度(单位:像素)
④ 图像宽度 2字节 图像宽度(单位:像素)
⑤ 颜色分量数 1字节 只有3个数值可选
1:灰度图;
3:YCrCb或YIQ;
4:CMYK
而JFIF中使用YCrCb,故这里颜色分量数恒为3
⑥颜色分量信息 颜色分量数×3字节(通常为9字节)
a)颜色分量ID 1字节
b)水平/垂直采样因子 1字节
高4位:水平采样因子
低4位:垂直采样因子
c) 量化表 1字节 当前分量使用的量化表的ID - DHT 定义哈夫曼表
标记代码 2字节 固定值0xFFC4
包含2个具体字段:
① 数据长度 2字节
② huffman表 数据长度-2字节
表ID和表类型 1字节
高4位:类型,只有两个值可选(0:DC直流;1:AC交流)
低4位:哈夫曼表ID,注意,DC表和AC表分开编码
不同位数的码字数量 16字节
编码内容 16个不同位数的码字数量之和(字节)
本标记段中,字段②可以重复出现(一般4次),也可以只出现1次。 - SOS 扫描开始
标记代码 2字节 固定值0xFFDA
包含2个具体字段:
①数据长度 2字节 ①~④两个字段的总长度
②颜色分量数 1字节 应该和SOF中的字段⑤的值相同,即:
1:灰度图是;3: YCrCb或YIQ;4:CMYK。
③颜色分量信息
a) 颜色分量ID 1字节
b) 直流/交流系数表号 1字节
高4位:直流分量使用的哈夫曼树编号
低4位:交流分量使用的哈夫曼树编号
④ 压缩图像数据
a)谱选择开始 1字节 固定值0x00
b)谱选择结束 1字节 固定值0x3F
c)谱选择 1字节 在基本JPEG中总为00
3.Huffman表存储方式
(1)理论说明
在标记段DHT内,包含了一个或者多个的哈夫曼表。对于单一个哈夫曼表,应该包括了三部分:
- 哈夫曼表ID和表类型
这个字节的值为一般只有四个0x00、0x01、0x10、0x11。
0x00表示DC直流0号表;
0x01表示DC直流1号表;
0x10表示AC交流0号表;
0x11表示AC交流1号表。 - 不同位数的码字数量
- 编码内容
JPEG文件的哈夫曼编码只能是1-16位的。这个字段的16个字节分别表示1~16位的编码码字在哈夫曼树中的个数。这个字段记录了哈夫曼树中各个叶子结点的权。所以,上一字段(不同位数的码字数量)的16个数值之和就应该是本字段的长度,也就是哈夫曼树中叶子结点个数。
(2)举例
- 红色部分
为哈夫曼表ID和表类型,其值0x00表示此部分数据描述的是DC交流0号表。 - 蓝色部分(16个字节)
为不同位数的码字的数量。这16个数值实际意义为:没有1位的哈夫曼码字;2位的码字有3个;3位-9位的码字各有1个;没有9位或以上的码字。 - 绿色部分(10个字节)
为编码内容。由蓝色部分数据知道,此哈夫曼树有0+3+1+1+1+1+1+1+1=10个叶子结点,即本字段应该有10个字节。这段数据表示10个叶子结点按从小到大排列,其权值依次为04、 05、 06、 03、 02、 01、 00、09、 07、 08 (16进制)
4.建立huffman树/表
在读出哈夫曼表的数据后,就要建立哈夫曼树。具体方法为:
(1)第一个码字必定为0
如果第一个码字位数为1,则码字为0;如果第一个码字位数为2,则码字为00;如此类推。
(2)从第二个码字开始
如果它和它前面的码字位数相同,则当前码字为它前面的码字加1;如果它的位数比它前面的码字位数大,则当前码字是前面的码字加1后再在后边添若干个0,直至满足位数长度为止。
如:
序号 | 码长 | 码字 | 权值 |
---|---|---|---|
1 | 2 | 00 | 4 |
2 | 2 | 01 | 5 |
3 | 2 | 10 | 6 |
4 | 3 | 110 | 3 |
5 | 4 | 1110 | 2 |
6 |