实验5:JPEG原理分析及JPEG解码器的调试(未完.)

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


二、理论知识
1.JPEG编码原理
在这里插入图片描述
(1)Level offset(零电平偏置)
(2)8*8DCT变换
(3)用根据人眼视觉特性设计的量化矩阵对DCT变换之后的结果进行量化
(4)
DC 系数编码: 由于直流系数 F(0,0)反映了该子图像中包含的直流成分,通常较大,又由 于两个相邻的子图像的直流系数通常具有较大的相关性,所以对 DC 系数采用 差值脉冲编码(DPCM),即对本像素块直流系数与前一像素块直流系数的差 值进行无损编码。

AC 系数编码: 首先,进行游程编码(RLC),并在最后加上块结束码(EOB);然后,系 数序列分组,将非零系数和它前面的相邻的全部零系数分在一组内;每组用两 个符号表示[(Run,Size),(Amplitude)]

2.JPEG解码流程
(1) 读取文件

(2)解析 Segment Marker

a 解析SOI 
b 解析APP0,检查标识“JFIF”及版本,得到一些参数 
c 解析DQT,得到量化表长度(可能包含多张量化表),得到量化表的精度 ,得到及检查量化表的序号(只能是 0 —— 3),得到量化表内容(64 个数据)
d 解析 SOF0,得到每个 sample 的比特数、长宽、颜色分量数  得到每个颜色分量的 ID、水平采样因子、垂直采样因子、使用的量化表 序号(与 DQT 中序号对应) 
e 解析DHT,得到 Huffman 表的类型(AC、DC)、序号,依据数据重建 Huffman 表 
f  解析SOS,得到解析每个颜色分量的 DC、AC 值所使用的 Huffman 表序号(与 DHT 中序号对应)

(3)依据每个分量的水平、垂直采样因子计算 MCU 的大小,并得到每个 MCU 中 8*8 宏块的个数

(4)对每个MCU解码(依照各分量水平、垂直采样因子对MCU中每个分量宏块解码)

a 对每个宏块进行Huffman解码,得到DCT系数
b 对每个宏块的 DCT 系数进行 IDCT,得到 Y、Cb、Cr
c 遇到 Segment Marker RST时,清空之前的 DC DCT 系数 

(5) 解析到 EOI,解码结束
(6) 将 Y、Cb、Cr 转化为需要的色彩空间并保存。

3.JPEG文件格式简述
(1)JPEG 在文件中以 Segment 的形式组织,它具有以下特点: 
均以 0xFF 开始,后跟 1 byte 的 Marker 和 2 byte 的 Segment length(包含表示 Length 本身所占用的 2 byte,不含“0xFF” + “Marker” 所占用的 2 byte);
采用 Motorola 序(相对于 Intel 序),即保存时高位在前,低位在后; 
Data 部分中,0xFF 后若为 0x00,则跳过此字节不予处理;
(2)Segment Marker



三、实验内容与相关结果
1.JPEG编解码原理以及结合C++程序的设计框架理解

2.逐步调试JPEG解码器程序。将输入的JPG文件进行解码,将输出文件保存为可供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 = fopen(temp, "wb");
  fwrite(components[2], width*height/4, 1, F);
 
  snprintf(temp, 1024, "%s.YUV", filename);
  F = fopen(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);
}

在这里插入图片描述
如图为jpg图像与解码输出的yuv图像(yuv图像按1024*1024显示)

3.三个结构体的设计目的
struct huffman_table–用于优化程序运行速度,lookup加速查表,失败则慢速查表;code_size指示已编码长度。

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像块的编码信息,便于解码等过程使用。Hfactor,Vfactor为水平,垂直采样因子。Q_table指向当前8×8块使用的量化表,Huffman_table对应当前块AC huffman表和DC huffman表,previous_DC为前一个宏块得DC系数,DCT[64]即存储了该宏块中8×8得DCT系数数值。

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];		/* DCT coef */
#if SANITY_CHECK
  unsigned int cid;
#endif
};


struct jdec_private–JPEG流结构体,在主程序中用此结构体存储解码后得到的JPEG流。包括以上两个结构体的信息以及图像的宽高信息,流长度信息,量化表和Huffman表信息等。

struct jdec_private
{
  /* Public variables */
  uint8_t *components[COMPONENTS];
  unsigned int width, height;	/* Size of the image */
  unsigned int flags;

  /* Private variables */
  const unsigned char *stream_begin, *stream_end;
  unsigned int stream_length;

  const unsigned char *stream;	/* Pointer to the current stream */
  unsigned int reservoir, nbits_in_reservoir;

  struct component component_infos[COMPONENTS];
  float Q_tables[COMPONENTS][64];		/* quantization tables */
  struct huffman_table HTDC[HUFFMAN_TABLES];	/* DC huffman tables   */
  struct huffman_table HTAC[HUFFMAN_TABLES];	/* AC huffman tables   */
  int default_huffman_table_initialized;
  int restart_interval;
  int restarts_to_go;				/* MCUs left in this restart interval */
  int last_rst_marker_seen;			/* Rst marker is incremented each time */

  /* Temp space used after the IDCT to store each components */
  uint8_t Y[64*4], Cr[64], Cb[64];

  jmp_buf jump_state;
  /* Internal Pointer use for colorspace conversion, do not modify it !!! */
  uint8_t *plane[COMPONENTS];

};

4.在视音频编解码调试中TRACE的目的和含义
含义:trace在程序运行过程中记录下重要的信息,如解析DHT,解析DQT,采用的采样频率等
目的:便于后期程序调试

会打开和关闭TRACE—
此处定义为0即可关闭

#define TRACE 1 

会根据自己的要求修改TRACE—
TRACE为1时,可以根据实际需要修改程序中形如下代码中xxx;处的内容

#if TRACE
//xxx;
#endif

5.以txt文件输出所有的量化矩阵和所有的HUFFMAN码表

6.输出DC图像并统计其概率分布

7.输出某一个AC值图像并统计其概率分布

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值