实验目的
掌握JPEG编解码系统的基本原理。初步掌握复杂的数据压缩算法实现,并能根据理论分析需要实现所对应数据的输出。
方法解释
JPEG文件格式

SOI

APP0

DQT

SOF0

DHT

SOS

EOI

JPEG编码原理

零偏置(Level Offset)
对于灰度级是2n的像素,通过减去2n-1,将无符号的整数值变成有符号数。
对于n=8,即将0 ~ 255的值域,通过减去128,转换为
值域在-128~127之间的值。
目的:使像素的绝对值出现3位10进制的概率大大减少
DCT变换
对每个单独的彩色图像分量,把整个分量图像分成8×8的图像块,如图所示,并作为两维离散余弦变换DCT的输入。

量化
根据人眼的视觉特性(对低频敏感,对高频不太敏感)对低频分量采取较细的量化,对高频分量采取较粗的量化

对DC系数编码
DC系数的差分编码
根据这个特点,JPEG算法使用了差分脉冲调制编码(DPCM)技术,对相邻图像块之间量化DC系数的差值DIFF进行编码:

DC系数的熵编码(huffman编码)
对DIFF用Huffman编码:分成类别,类似指数Golomb编码
➢类别ID:一元码编码
➢ 类内索引:采用定长码

对AC系数编码
AC系数的Z字扫描
由于经DCT变换后,系数大多数集中在左上角,即低频分量区,因此采用Z字形按频率的高低顺序读出,可以出现很多连零的机会。可以使用游程编码。尤其在最后,如果都是零,给出EOB (End of Block)即可。

AC系数的游程编码、熵编码(huffman编码)


实验步骤
1.逐步调试JPEG解码器程序。将输入的JPG文件进行解码,将输出文件保存为可供YUVViewer观看的YUV文件。
参数项目设置

修改load.jpeg中的write_yuv函数,添加注释代码以输出yuv文件
/**
* Save a buffer in three files (.Y, .U, .V) useable by yuvsplittoppm
*/
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);
fopen_s(&F,temp, "wb");
fwrite(components[0], width, height, F);
fclose(F);
snprintf(temp, 1024, "%s.U", filename);
fopen_s(&F,temp, "wb");
fwrite(components[1], width * height / 4, 1, F);
fclose(F);
snprintf(temp, 1024, "%s.V", filename);
fopen_s(&F,temp, "wb");
fwrite(components[2], width * height / 4, 1, F);
fclose(F);
//输出yuv文件
snprintf(temp, 1024, "%s.yuv", filename);
fopen_s(&F, temp, "wb");
fwrite(components[0], width, height, F);
fwrite(components[1], width * height / 4, 1, F);
fwrite(components[2], width * height / 4, 1, F);
fclose(F);
}
输入test.jpg如下图

输出test.yuv,并用YUV viewer打开


2. 程序调试过程中,应做到:
理解程序设计的整体框架
理解三个结构体的设计目的
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];
};
struct component
储存8×8图像块中解码用表的信息
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

最低0.47元/天 解锁文章
2655

被折叠的 条评论
为什么被折叠?



