【实验原理】
1.JPEG的编码原理
下图为基本(baseline) JPEG编码器
(1)零偏置:即把[0,255]的像素值减128变为[-128,127];(对于灰度级是2n的像素,通过减去2n-1,将无符号 的整数值变成有符号数,使像素的绝对值出现3位10进制的概率大大 减少)
(2)8×8DCT变换:能量集中和去相关,减小空间冗余;
(3)量化:根据人眼视觉特性,低频细量化,高频粗量化,减小视觉冗余;
(4)编码:直流系数进行差分和VLC编码,交流系数进行之字形扫描、游程编码和VLC编码,减少数据冗余。
2.JPEG文件格式
2.1 Segment 的组织形式
- Segment 的组织形式 JPEG 在文件中以 Segment 的形式组织,它具有以下特点: 均以 0xFF 开始,后跟 1 byte
的 Marker 和 2 byte 的 Segment length(包含表示 Length 本身所占用的 2 byte,不含“0xFF” - “Marker” 所占用的 2 byte); 采用 Motorola 序(相对于 Intel 序),即保存时高位在前,低位在后;
- Data 部分中,0xFF 后若为 0x00,则跳过此字节不予处理;
2.2 JPEG 的 Segment Marker
3. JPEG 的解码流程
3.1 读取文件
3.2 解析 Segment Marker
3.2.1 解析 SOI
3.2.2 解析 APP0
检查标识“JFIF”及版本
得到一些参数
3.2.3 解析 DQT
得到量化表长度(可能包含多张量化表)
得到量化表的精度 得到及检查量化表的序号(只能是 0 —— 3)
得到量化表内容(64 个数据)
3.2.4 解析 SOF0
得到每个 sample 的比特数、长宽、颜色分量数
得到每个颜色分量的 ID、水平采样因子、垂直采样因子、使用的量化表 序号(与 DQT 中序号对应)
3.2.5 解析 DHT
得到 Huffman 表的类型(AC、DC)、序号
依据数据重建 Huffman 表 3.2.6 解析 SOS
得到解析每个颜色分量的 DC、AC 值所使用的 Huffman 表序号(与 DHT 中序号对应)
3.3 依据每个分量的水平、垂直采样因子计算 MCU 的大小,并得到每个 MCU 中 8*8 宏块的个数
3.4 对每个 MCU 解码(依照各分量水平、垂直采样因子对 MCU 中每个分量宏块解 码)
3.4.1 对每个宏块进行 Huffman 解码,得到 DCT 系数
3.4.2 对每个宏块的 DCT 系数进行 IDCT,得到 Y、Cb、Cr
3.4.3 遇到 Segment Marker RST 时,清空之前的 DC DCT 系数
3.5 解析到 EOI,解码结束 3.6 将 Y、Cb、Cr 转化为需要的色彩空间并保存
【实验过程】
step1:输出YUV文件
static void write_yuv(const char *filename, int width, int height, unsigned char **components)
{
FILE *F;
char temp[1024];
snprintf(temp, 1024, "%s.Y", filename);
F = fopen