一、基本原理
JPEG编码的过程如图所示:
- 将图像分成(8*8)的块以便进行DCT变换,不够的要取边缘像素补齐
- 零偏置:对于灰度级是2n的像素,通过减去2n-1,将无符号的整数值变成有符号数,对于n=8,即将0~255的值域,通过减去128,转换为值域在-128~127之间的值,使像素的绝对值出现3位10进制的概率大大减少。
- DCT:经过DCT变换后,图像中的低频分量会集中在左上角,低频能量高,故而左上角数值较大。
- 量化:根据人眼的视觉特性,对低频敏感所以细量化,对高频不敏感所以粗量化;对亮度信号敏感,对色度信号不敏感。所以亮度和色度分量分别采用不同的量化表。
- 之字形扫描:游程编码的扫描过程,由于DCT变换后,系数集中在左上角,于是采用之字形扫描。
- 熵编码:直流分量采用差分编码;交流分量采用游程编码
解码过程:
- 读入文件的相关信息
- 初步了解图像数据流的结构
- 颜色分量单元的内部解码
- 直流系数的差分编码
- 反量化 & 反Zig-zag编码
- 反离散余弦变换
JPEG文件格式
- SOI 0xFFD8 图像开始
- APPn 0xFFEn 应用细节信息
- DQT 0xFFDB 定义量化表
- SOF0 0xFFC0 帧图像开始
- DHT 0xFFC4 定义霍夫曼表
- SOS 0xFFDA 扫描开始 12字节
- EOI 0xFFD9 图像结束 2字节
二、实验流程
(1).逐步调试JPEG解码器程序。将输入的JPG文件进行解码,将输出文件保存为可供YUVViewer观看的YUV文件。
(2). 程序调试过程中,应做到:
- 理解程序设计的整体框架
- 理解三个结构体的设计目的
- struct huffman_table
- struct component
- struct jdec_private
- 理解在视音频编解码调试中TRACE的目的和含义
- 会打开和关闭TRACE
- 会根据自己的要求修改TRACE
(3).以txt文件输出所有的量化矩阵和所有的HUFFMAN码表。
(4). 输出DC图像并经过huffman统计其概率分布(使用第三个实验中的Huffman编码器)。
(5). 输出某一个AC值图像并统计其概率分布(使用第三个实验中的Huffman编码器)。
三、关键代码及分析
1.将输出文件保存为YUV文件
tinyjpeg.h
enum tinyjpeg_fmt {
TINYJPEG_FMT_GREY = 1,
TINYJPEG_FMT_BGR24,
TINYJPEG_FMT_RGB24,
TINYJPEG_FMT_YUV420P, //add by cxy
TINYJPEG_FMT_YUV,
};
tinyjpeg.c
int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)
{.. /*add by cxy*/
case TINYJPEG_FMT_YUV:
colorspace_array_conv = convert_colorspace_yuv420p;
if (priv->components[0] == NULL)
priv->components[0] = (uint8_t *)malloc(priv->width * priv->height);
if (priv->components[1] == NULL)
priv->components[1] = (uint8_t *)mall