JPEG原理分析及JPEG解码器的调试
一.实验原理
1.JPEG编码原理
2.JPEG文件格式
SOI start of image 图像开始
标记代码 2字节 固定值0xFFD8
APP0 appllication 应用程序保留标记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 define quantization table 定义量化表
标记代码 2字节 固定值0xFFDB
包含9个具体字段:
①数据长度 2字节 字段①和多个字段②的总长度
②量化表 数据长度-2字节
a) 精度及量化表ID 1字节
高4位:精度,只有两个可选值 0:8位;1:16位
低4位:量化表ID,取值范围为0~3
b) 表项 (64×(精度+1))字节
例如8位精度的量化表,其表项长度为64×(0+1)=64字节
本标记段中,字段②可以重复出现,表示多个量化表,但最多只能出现4次
SOF0 start of frame 帧图像开始
标记代码 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 define huffman table 定义哈夫曼表
标记代码 2字节 固定值0xFFC4
包含2个具体字段:
①数据长度 2字节
②huffman表 数据长度-2字节
表ID和表类型 1字节
高4位:类型,只有两个值可选
0:DC直流;1:AC交流
低4位:哈夫曼表ID,
注意,DC表和AC表分开编码
不同位数的码字数量 16字节
编码内容 16个不同位数的码字数量之和(字节)
本标记段中,字段②可以重复出现(一般4次),也可以只出现1次。
SOS start of scan 扫描开始12字节
标记代码 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
EOI end of image 图像结束
标记代码 2字节 固定值0xFFD9
二.实验流程
1.将输出文件保存为可供YUVViewer观看的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(temp, "wb");
fwrite(components[0], width, height, F);
fclose(F);
snprintf(temp, 1024, "%s.U", filename);
F = fopen(temp, "wb");
fwrite(components[1], width*height/4, 1, F);
fclose(F);
snprintf(temp, 1024, "%s.V", filename);
F