【数据压缩】Exp05.JPEG解码

实验原理:

01.JPEG的编解码原理:


输入图像的YUV数据先进行偏置,再将图片按8x8的块进行DCT变换编程8x8的系数块,接着再根据8x8的量化表对系数块进行量化,量化后的8x8的系数块需要对其进行不同的操作,其中左上角的直流系数进行,交流系数先之字形扫描,再根据对应的AC霍夫曼码表进行可变长编码(VLC编码),得到编码输出。

JPEG的解码过程就是编码的逆过程,要想从一张.jpg格式的文件得到图像的原始yuv数据,则在熟悉解码过程的基础上还要了解.jpg文件的数据组织格式

02.JPEG文件格式分析:

文件以segment的方式组织。每一个segment的特点如下:

1.0xFF(一字节)marker(一字节)segment length(两字节,用来表示该segment的长度,包括segment length的两字节,不包括0xFFmarker的两字节)

2.采用Motorola序(相对于Intel序),即高位在前,低位在后;

3.Data部分中,若FF后为00,则跳过这字节不处理。

以本次实验所用的文件为例进行分析(仅截取部分图像数据),按顺序依次有一下的标识符:


FFD8SOI,图像的开始,所有jpeg文件都必须以这个开头;

FFE0:应用程序保留标记0

FFDB:定义量化表,每个文件最多有四张量化表,此次实验所用图片中共有2FFDB,因此共有2张量化表;

FFC0SOF0,帧图像开始;

FFC4:定义霍夫曼表,本文件中共有4FFC4,因此共有4张霍夫曼码表;

FFDASOS,扫描开始;

FFD9:图像结束。

实验程序分析:

本次实验的程序中共有三个结构体用来存储数据:huffman_table,component,jdec_private,这三个结构体之间是依次被包含的关系,对应了图像数据的三个层次。

huffman_table


component:


jdec_private:


解码流程如下:

1.在主函数中打开文件,将图像数据读入到缓存区中;

2.按顺序依次解析segment marker,在解析的过程中得到图像相关的参数并生成霍夫曼码表和量化表,为之后的解码做准备;

3.根据每个分量的水平、垂直采样分子计算MCU的大小,计算每个MCU中有多少8x8的块;

4.对每个MCU进行解码,

5.解析到EOI,解析结束;

6.将解析生成的YCbCr照要求转换为需要的彩色空间并输出。

在解析的过程中会同时输出trace文件,输出一些图像相关的参数及信息帮助理解解码过程及文件的结构,若想关闭只需要将tinyjpeg.h中的TRACE变量设为1

实验结果分析:

第一步:将.jpg图像转换为.yuv文件并查看,代码如下:


输出的yuv文件如下:


第二步:将该文件中所有的霍夫曼码表输出到一个txt文件中,代码如下:

01.先声明文件指针变量,这一步最开始我考虑的是将文件指针变量声明在main函数中,但是之后发现这样就得在很多函数中加入文件指针的形参,很容易就混淆造成程序有bug,因此这种方法不可行,最后仿照trace文件指针声明方法将其声明在头文件中,作为全局变量:


02.在主函数中打开文件:


03.在主函数末尾关闭文件:


04.输出霍夫曼码表(包括符号值、对应码字、对应码长,代码添加在build_huffman_tableparse_DHT中):


05.最终输出的码表结果如下:


可以看到这张图片包含了四张霍夫曼码表,与上面分析文件数据时的结论相同。


第三步:输出文件中所有的量化表,代码如下:

(文件相关操作已包含在第二步)

添加在make_quantization_table中的代码,其中的zz是一个表示位置的8x8的数组,由于在图片编码时对DCT变换后的数据要进行之字形扫描,因此在解码时需要将数据恢复到其原来的位置,因此用一个表示位置的数组来将ref_table中的数重新排列放在q_table中:


添加在parse_DQT函数中的代码:



最终得到的量化表是:


可以看到该文件只有两张量化表,与文件分析的结论相同。

第四步:输出每个块的直流系数和一个交流系数,并分析其数据的概率分布:


输出的DC图像和AC图像如下,原始图像的尺寸为1024x1024,该图像中的块是16x16的,因此AC图像和DC图像的尺寸为64x64DC图像能看清楚图像的大概轮廓,说明图像的直流分量包含了图像的大部分信息。AC图像随着频率的增高其轮廓越不明显,说明了DCT变换的能量集中的特性,高频部分的值很小。


DCAC图像的数据进行概率分布的统计,结果如下:

DC


AC:





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值