目录
一、实验目的
掌握JPEG编解码系统的基本原理。初步掌握复杂的数据压缩算法实现,并能根据理论分析需要实现所对应数据的输出。
二、JPEG编解码原理
JPEG是一种针对数字图像的有损压缩标准方法,由于JPEG编码算法可以在提供较大的压缩比的同时,保持较好的显示质量,所以该算法逐渐成为最为熟知和广泛使用的数字图像格式和通用标准。
1. JPEG编码器的系统原理框图
(1)JPEG编码器
(2)JPEG解码器
2. 各环节作用
(1) 零偏置
对于灰度级为2n 的像素,通过减去2(n-1),将无符号整数变为有符号数,以将绝对值大的数出现的概率大大减小,提高编码效率。
(2) 8×8 DCT
对每个单独的彩色图像分量,把整个分量图像分成8*8的图像块,作为二维离散余弦变换DCT的输入,并进行DCT变换。以实现能量集中和去相关,便于去除空间冗余,提高编码效率。(若图像的宽或高不是8的整数倍的图像,使用图像边缘像素填充,以不改变频谱分布。)DCT是一种无损变换,也无法对图像进行压缩,这样做的目的是在为下一步的量化做准备。
(3) 量化
量化是编码流程中唯一会引入误差也是唯一会带来压缩效果的步骤。 由于人眼对亮度信号比对色差信号更敏感,因此JPEG使用了两种量化表:亮度量化值和色差量化值。根据人眼对低频敏感,对高频不太敏感的视觉特性,对低频部分采取细量化,对高频部分采取粗量化,减少了视觉冗余。量化矩阵并不是固定的,可以根据要求的质量的不同而进行调整。但经过量化,子块中的大多数高频区域的系数的量化结果都为0。
(4) DC系数差分编码
经过8*8DCT变换后,DC直流系数的数值都比较大,且相邻图像块之间的DC系数变化不大(容易造成冗余),因此JPEG算法使用了差分脉冲调制编码DPCM技术对相邻图像块之间的量化DC系数的差值DIFF进行编码。
(5) AC系数Zig-Zag扫描与游程编码
经过DCT变换后,AC系数大多集中在左上角的低频分量区,因此采用Z字形按频率的高低顺序读出可以出现很多连零的情况,便于使用游程编码,若最后的数据均为0,则直接给出EOB。
(6) Huffman编码
对DC系数DPCM的结果和AC系数RLE的结果进行Huffman编码,类别ID采用一元码编码,类内索引采用定长码编码。共有亮度DC、亮度AC、色差DC、色差AC四张码表。
三、JPEG文件格式分析
缩写 | 全称及中文名称 | 固定值 | 详细 |
---|---|---|---|
SOI | Start of Image 图像开始 | 0xFFD8 | |
EOI | End of Image 图像结束 | 0xFFD9 | |
APP0 | Application应用程序保留标记0 | 0xFFE0 | |
DQT | Define Quantization Table 定义量化表 | 0xFFDB | |
SOF0 | Start of Frame 帧图像开始 | 0xFFC0 | |
DHT | Define Huffman Table 定义哈夫曼表 | 0xFFC4 | |
SOS | Start of Scan 扫描开始 12字节 | 0xFFDA |
四、JPEG解码流程及核心代码说明
1. 三个重要的结构体
- struct huffman_table:存储Huffman码表。
struct huffman_table
{
/* Fast look up table, using HUFFMAN_HASH_NBITS bits we can have directly the symbol,
* if the symbol is <0, then we need to look into the tree table */
short int lookup[HUFFMAN_HASH_SIZE];//得到该权值对应的码字
/* code size: give the number of bits of a symbol is encoded */
unsigned char code_size[HUFFMAN_HASH_SIZE];//得到该权值对应的码长
/* some place to store value that is not encoded in the lookup table
* FIXME: Calculate if 256 value is enough to store all values
*/
uint16_t slowtable[16-HUFFMAN_HASH_NBITS][256];//码长大于9时由该表处理
};
- struct component:储存当前8×8像块中有关解码的信息。
struct component
{
unsigned int Hfactor;//水平采样因子
unsigned int Vfactor; //垂直采样因子
float *Q_table;//指向该8×8块使用的量化表
struct huffman_table *AC_table;//指向该块使用的AC Huffman表
struct huffman_table *DC_table;// 指向该块使用的DC Huffman表
short int previous_DC;