一、实验目的
掌握JPEG编解码系统的基本原理。初步掌握复杂的数据压缩算法实现,并能根据理论分析需要实现所对应数据的输出。
二、实验环境
安装Windows和Visual Studio软件的个人计算机
三、实验内容
1.JPEG编解码原理
图示为JPEG编码过程图,解码时编码的逆过程
1)彩色空间
JPEG标准本身没有规定具体的颜色空间,只是对各分量分别进行编码。实现中通常将高度相关到的RGB颜色空间转换到相关性较小的YUV颜色空间。图像的主要信息包括在Y通道,U、V更平滑,更易压缩。由于人眼对色度分量不敏感,可以对色度分量进行下采样。
2)进行8x8的DCT变换,实现能量集中和去相关,降低空间冗余度
3)零偏置
对于灰度级是2^n的像素,通过减去2^(n-1)将无符号数转变为有符号数。对于n=8,即值域为0~255,通过减去128,将值域转换为-128~127,目的是使像素的绝对值出现3位10进制的概率大大减少。
4)进行均匀量化,使用根据人眼特性制作的量化表,特点是低频细量化,高频粗量化
5)对直流系数进行差分和VLC编码,对交流系数使用zig-zag扫描和游程编码,再进行VLC编码
2.JPEG文件格式
JPEG在文件中以Segment的形式组织,具有以下特点:
- 均以0xFF开始,后跟1byte的Marker和2byte的Segment Length(包含length本身所占用的2byte,不含“0xFF”+"Marker"所占用的2byte)
- 采用Motorola序,即保存时高位在前,低位在后
- Data部分中,0xFF后若为0x00,则跳过次字节不予处理
四、实验步骤
(一)
struct huffman_table 存储哈夫曼表,实现快速查找
快速查找表,使用HUFFMAN_HASH_NBITS位,我们可以直接查找到符号,如果符号值<0,还需要去查看树表
给出已编码符号的比特数
一些空间用于存储在查找表中未被编码的值
计算256的值域是否足够存储所有值
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];
};
struct component 定义水平、垂直采样因子和DCT系数
定义水平采样因子和垂直采样因子以及DCT系数,直流哈夫曼表,交流哈夫曼表,前直流系数
struct component
{
unsigned int Hfactor;
unsigned int Vfactor;
float *Q_table; /* Pointer to the quantisation table to use */
struct huffman_table *AC_table;
struct huffman_table *DC_table;
short int previous_DC; /* Previous DC coefficient */
short int DCT[64]; /* DCT coef */
#if SANITY_CHECK
unsigned int cid;
#endif
};
struct jdec_private 指示解码中的所有信息
包含输出中可接受的格式
可以被设立在任何应用中的标识
其共有变量,包含图片大小
其私有变量,指向当前流的指针
Component的信息:量化表,直流哈夫曼表,交流哈夫曼表
struct jdec_private
{
/* 公有变量 */
uint8_t *components[COMPONENTS];
unsigned int width, height; /* Size of the image */
unsigned int flags;
/* 私有变量 */
const unsigned char *stream_begin, *stream_end;
unsigned int stream_length;
const unsigned char *stream; /* Pointer to the current stream */
unsigned int reservoir, nbits_in_reservoir;
struct component component_infos[COMPONENTS];
float Q_tables[COMPONENTS][64]; /* quantization tables */
struct huffman_table HTDC[HUFFMAN_TABLES]; /* DC 哈夫曼表 */
struct huffman_table HTAC[HUFFMAN_TABLES]; /* AC 哈夫曼表 */
int default_huffman_table_initialized;
int restart_interval;
int restarts_to_go; /* 在此重启间隔内剩余的MCU */
int last_rst_marker_seen; /* Rst 标记每次的递增 */
/* 反DCT变换后用于存储每个component的临时空间 */
uint8_t Y[64*4], Cr[64], Cb[64];
jmp_buf jump_state;
/* 用于实现色彩空间转换的内部指针, d