1.实验原理

1.1 JPEG算法概要

JPEG(Joint Photographic Experts Group)是一个由ISO和IEC两个组织机构联合组成的一个专家组,负责制定静态的数字图像数据压缩编码标准,这个专家组开发的算法称为JPEG算法,并且成为国际上通用的标准,因此又称为JPEG标准。JPEG是一个适用范围很广的静态图像数据压缩标准,既可用于灰度图像又可用于彩色图像。

1.2 Z字形编排

量化后的系数要重新编排,目的是为了增加连续的“0”系数的个数,就是“0”的游程长度,方法是按照Z字形的式样编排,如下图所示。这样就把一个8×8的矩阵变成一个1×64的矢量,频率较低的系数放在矢量的顶部。

1.3 DCT 系数熵编码原理

1.3.1  DC 系数编码: 由于直流系数 F(0,0)反映了该子图像中包含的直流成分,代表8*8个子块的平均值,通常较大,又由 于两个相邻的子图像的直流系数通常具有较大的相关性,所以对 DC 系数采用 差值脉冲编码(DPCM),即对本像素块直流系数与前一像素块直流系数的差值进行无损编码。

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

1.4 JPEG文件的量化表与码表

JPEG使用的颜色是YUV格式。Y分量代表了亮度信息,UV分量代表了色差信息。由人的视觉特性,亮度分量Y分量更重要一些。我们可以对Y采用细量化,对UV采用粗量化,可进一步提高压缩比。所以上面所说的量化表通常有两张,一张是针对Y的,一张是针对UV的,而最后的文件应该有四张码表:亮度的DC、AC码表,色度的DC、AC码表

1.5 JPEG文件的组织形式

n SOI(0xFFD8),Start of Image,图像开始

n APP0(0xFFE0),Application,应用程序保留标记0

n DQT(0xFFDB),Define Quantization Table,定义量化表

n SOF0(0xFFC0),Start of Frame,帧图像开始

n DHT(0xFFC4),Define Huffman Table,定义哈夫曼表

n SOS(0xFFDA),Start of Scan,扫描开始 12字节

压缩数据

n  EOI(0xFFD9)End of Image,图像结束 2字节

1.5.2文件组织流格式理解举例

注:加粗部分即为JPEG文件存储数据

FFD8: SOI(Start of Image,图像开始)

所有的 JPEG 文件必须以 SOI 开始

FFE0: APP0(Application,应用程序保留标记-0) length: 16 byte (2 byte)

0010 4A 46 49 46 00 01 01 01 00 48 00 48 0000 

标识符: JFIF   (5 byte) Version:0101   (2 byte) Units: 01 (1 byte)

X and Y are dots per inch Xdensity:72  (2bytes)

Horizontal pixel density(水平方向点密度) Ydensity: 72  (2 bytes)

Vertical pixel density(垂直方向点密度)

缩略图水平像素数目: 00  (1 byte) 缩略图垂直像素数目: 00  (1 byte)

缩略图 24bitRGB 点数目: 缩略图水平像素数目 * 缩略图垂直像素数目 =00  (1 byte)

FFDB: DQT,Define Quantization Table,定义量化表 length: 67byte  (2 byte)

00 43 00 08 06 06 07 06 05 08 07 07 07 09 09 08 0A 0C 140D 0C 0B 0B 0C 19 12 13 

0F 14 1D 1A 1F 1E 1D 1A 1C 1C 20 24 2E 27 20 22 2C 231C 1C 28 37 29 2C 30 31 

34 34 34 1F 27 39 3D 38 32 3C 2E 33 34 32 

QT information - precision: 00  (Higher 4bit)   (8 bit) QT information - index: 00  (Lower 4bit)

qt_table:

i: 00  value:   8 i: 01  value:    6 i: 02 value:    6 i: 03  value:   7

i: 04  value:   6 i: 05  value:    5 i: 06 value:    8 i: 07  value:   7

i: 08  value:   7 i: 09  value:    7 i: 10 value:    9 i: 11 value:    9

i: 12  value:   8 i: 13  value:   10 i: 14 value:   12 i: 15  value:  20

i: 16  value:  13 i: 17  value:   12 i: 18 value:   11 i: 19  value:  11

i: 20  value:  12 i: 21  value:   25 i: 22 value:   18 i: 23  value:  19

i: 24  value:  15 i: 25  value:   20 i: 26 value:   29 i: 27  value:  26

i: 28  value:  31 i: 29  value:   30 i: 30 value:   29 i: 31  value:  26

i: 32  value:  28 i: 33  value:   28 i: 34 value:   32 i: 35  value:  36

i: 36  value:  46 i: 37  value:   39 i: 38 value:   32 i: 39  value:  34

i: 40  value:  44 i: 41  value:   35 i: 42 value:   28 i: 43  value:  28

i: 44  value:  40 i: 45  value:   55 i: 46 value:   41 i: 47  value:  44

i: 48  value:  48 i: 49  value:   49 i: 50 value:   52 i: 51  value:  52

i: 52  value:  52 i: 53  value:   31 i: 54 value:   39 i: 55  value:  57

i: 56  value:  61 i: 57  value:   56 i: 58 value:   50 i: 59  value:  60

i: 60  value:  46 i: 61  value:   51 i: 62 value:   52 i: 63  value:  50

此为第一张量化表,量化表标记代码:FFDB

量化表长度:(67byte),长度本身占 2 字节, 

精度及量化表 ID: 1byte, 低位为量化表的 ID 的索引值,其取值范围为 0~3,所以说最多可能有四张量化表(亮度量化表,色度量化表,可能会有 R、G、B 各一张量化表);而高位为量化精度,有两个可选值,0:8 位;1:16 位,这里是 00,代表量化精度为 8bit,即用一个字节来表示一个量化系数

数据:64 字节的量化系数,(一个字节对应一个量化系数,对于8*8 的宏块来说,共 8*8=64 个量化系数)

FFDB:DQT(Define Quantization Table),定义量化表 length: 67byte  (2 byte)

00 43 01 09 09 09 0C 0B 0C 18 0D 0D 18 32 21 1C 21 32 3232 32 32 32 32

 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 3232 32 32 32

 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32

QT information - precision: 00  (Higher 4bit)   (8 bit)

QT information - index: 01  (Lower 4bit)

qt_table:

i: 00  value:   9 i: 01  value:    9 i: 02 value:    9 i: 03  value:  12

i: 04  value:  11 i: 05  value:   12 i: 06 value:   24 i: 07  value:  13

i: 08  value:  13 i: 09  value:   24 i: 10 value:   50 i: 11  value:  33

i: 12  value:  28 i: 13  value:   33 i: 14 value:   50 i: 15  value:  50

i: 16  value:  50 i: 17  value:   50 i: 18 value:   50 i: 19  value:  50

i: 20  value:  50 i: 21  value:   50 i: 22 value:   50 i: 23  value:  50

i: 24  value:  50 i: 25  value:   50 i: 26 value:   50 i: 27  value:  50

i: 28  value:  50 i: 29  value:   50 i: 30 value:   50 i: 31  value:  50

i: 32  value:  50 i: 33  value:   50 i: 34 value:   50 i: 35  value:  50

i: 36  value:  50 i: 37  value:   50 i: 38 value:   50 i: 39  value:  50

i: 40  value:  50 i: 41  value:   50 i: 42 value:   50 i: 43  value:  50

i: 44  value:  50 i: 45  value:   50 i: 46 value:   50 i: 47  value:  50

i: 48  value:  50 i: 49  value:   50 i: 50 value:   50 i: 51  value:  50

i: 52  value:  50 i: 53  value:   50 i: 54 value:   50 i: 55  value:  50

i: 56  value:  50 i: 57  value:   50 i: 58 value:   50 i: 59  value:  50

i: 60  value:  50 i: 61  value:   50 i: 62 value:   50 i: 63  value:  50

此为第二张量化表,不同的是上张表的索引号为 00,这张表的索引号为 01,在后面的 SOF0 的部分中我们将会知道上张表对应亮度量化表,这张表对应色度量化表,对这张图来说就这两张量化表。

FFC0: SOF0 (Start of Frame,基线离散余弦变换) length: 17 byte  (2 byte)

00 11 08 01 C2 01 3B 03 01 11 00 02 11 01 03 11 01

图像精度(每个数据样本的位数): 8  Image Height: 450  (2 byte) Image Width: 315  (2 byte) 颜色分量数: 03(YCrCb)  (1 byte)

颜色分量 ID: 01  (1 byte)(Y) SampRate_Y_H: 01  (Higher 4bit) SampRate_Y_V: 01  (Lower 4 bit) YQtTableID: 00  (1 byte)

颜色分量 ID: 02  (1 byte)(U) SampRate_U_H: 01  (Higher 4bit) SampRate_U_V: 01  (Lower 4 bit) U QtTableID:01  (1 byte)

颜色分量 ID: 03  (1 byte)(V) SampRate_V_H: 01  (Higher 4 bit)SampRate_V_V: 01  (Lower 4 bit) VQtTableID: 01  (1 byte)

SOF0: start of frame,帧图像开始 

数据长度:长度本身占 2byte  图像精度: 1byte, 这里是 08,即精度为一个字节。 

图像高度:2 byte, 以像素为单位。图像宽度:2 byte, 以像素为单位。 

颜色分量数:一个字节,这里是 03,代表有三个分量,YCrCb。 

颜色分量信息:每个分量有三个字节,第一个为分量的 ID,01:Y 02:U 03: V;第二个字节高位为水平采样因子,低位为垂直采样因子,这里三个分量的采样率相同,所以采样格式为 4:4:4;第三个字节代表这个分量对应的量化表 ID,可以看出,Y 对应的量化表 ID 索引值为 00,而 UV 对应的量化表 ID 都为01,即它们共用一张量化表。 

所以,除了标记外,总共的长度就为 2+1+5+3*3=17

FFC4:DHT(Define Huffman Table,定义 Huffman 树表)

001C 00 00 02 03 01 0101 01 00 00 00 00 00 00 00 00 00 03 04 01 02 05 06 00 07 08  length: 28byte  (2 byte)

Huffman 表类型: 0  (Higher 4 bit) (DC)Huffman 表 ID: 0  (Lower 4 bit) (0 号表) HuffmanTableIndex: 0 code_len_table: (16 byte)

CodeLength: 01 00 个 CodeLength: 02 02 个 CodeLength: 0303 个

CodeLength: 04 01 个 CodeLength: 05 01 个 CodeLength: 0601 个

CodeLength: 07 01 个 CodeLength: 08 00 个 CodeLength: 0900 个

CodeLength: 10 00 个 CodeLength: 11 00 个 CodeLength: 1200 个

CodeLength: 13 00 个 CodeLength: 14 00 个 CodeLength: 1500 个

CodeLength: 16 00 个

FFC4:标记代码,2 字节,代表定义 Huffman 表。 

数据长度: 2 字节这里是 28 字节的长度(包括长度自身) 

Huffman 表 ID 号和类型:1 字节,高 4 位为表的类型,0:DC 直流;1:AC 交流可以看出这里是直流表;低四位为 Huffman 表 ID。 

可以看出这张表是直流 DC 的第 0 张表,在后面的扫描开始的部分中我们可以获右为亮度的直流系数表。 

不同长度 Huffman 的码字数量:固定为 16 个字节,每个字节代表从长度为 1 到长度为 16 的码字的个数,以表中的分析,这 16 个字节之后的 2+3+1+1+1+1=9 个字节对应的就是每个符字对应的权值,这些权值的含义即为 DC 系数经 DPCM 编码后幅度值的位长,03表示前3个码字码长都为2,04表示第4个-第7个码字码长都为3,依次按权值顺序写入编码数据。

通过上面的码长与码字个数的关系来生成相应码长的码字,再对应上之后的权值即位长根据解码得到的位长来读取之后相应长度的码字,再查上面这张可变长二进制编码表,就可以得到直流系数的幅度值,注意这个幅度值是经过DPCM 差分编码得到的。

这张图片中共有四张 Huffman 表

FFC4:DHT(Define Huffman Table,定义 Huffman 树表)

0045 10 00 01 03 02 0403 05 05 05 06 05 02 06 03 00 00 

01 00 02 03 04 11 05 12 21 31 41 51 61 06 13 22 71 81 32 91 A1 B1 C1 14 23

42 52 D1 07 15 72 E1 F0 F1 33 43 53 62 82 16 92 24 34 73 A2 B2 C2 63 74 83

length: 69 byte  (2 byte)

Huffman 表类型: 1  (Higher 4bit) (AC) Huffman 表 ID: 0  (Lower 4 bit)(0 号表) HuffmanTableIndex: 2 code_len_table: (16 byte)

CodeLength: 01 00 个 CodeLength: 02 01 个 CodeLength: 0303 个

CodeLength: 04 02 个 CodeLength: 05 04 个 CodeLength: 0603 个

CodeLength: 07 05 个 CodeLength: 08 05 个 CodeLength:09 05 个

CodeLength: 10 06 个 CodeLength: 11 05 个 CodeLength: 1202 个

CodeLength: 13 06 个 CodeLength: 14 03 个 CodeLength: 1500 个

CodeLength: 16 00 个

交流系数表: 它和直流系数表的权值代表的含义与解码方式有一定的差别,

交流系数权值的高位代表游程 run 的值,低位与直流系数相同,代表幅度的

位长 Size。在得到位长后还是要查可变长二制编码表来得到真正的AC 幅值。

例如:权值为0X01.可表示为(0,1)。表明此交流系数前无0,而此交流系

数的具体值还需要再读入1个bit的码字,才能得到。

FFC4:DHT(Define Huffman Table,定义 Huffman 树表)

0019 01 00 03 01 01 0100 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04 05

length: 25 byte  (2 byte)

Huffman 表类型: 0  (Higher 4 bit) (DC) Huffman 表 ID: 1  (Lower 4 bit) (1 号表) HuffmanTableIndex: 1 code_len_table: (16 byte)

CodeLength: 01 00 个 CodeLength: 02 03 个 CodeLength: 0301 个

CodeLength: 04 01 个 CodeLength: 05 01 个 CodeLength: 0600 个

CodeLength: 07 00 个 CodeLength: 08 00 个 CodeLength: 0900 个

CodeLength: 10 00 个 CodeLength: 11 00 个 CodeLength: 1200 个

CodeLength: 13 00 个 CodeLength: 14 00 个 CodeLength: 1500 个

CodeLength: 16 00 个

FFC4:DHT,Define Huffman Table,定义 Huffman 树表00 2A 11 

01 01 00 02 02 02 02 0203 00 02 02 03 01 00 00 00 01 02 11 03 

21 12 31 41 51 04 22 13 32 61 4271 33 52 05 14 23 A1

length: 42 byte  (2 byte)

Huffman 表类型: 1  (Higher 4 bit) (AC) Huffman 表 ID: 1  (Lower 4 bit) (1 号表) HuffmanTableIndex: 3 code_len_table: (16 byte)

CodeLength: 01 01 个 CodeLength: 02 01 个 CodeLength: 0300 个

CodeLength: 04 02 个 CodeLength: 05 02 个 CodeLength: 0602 个

CodeLength: 07 02 个 CodeLength: 08 02 个 CodeLength: 0903 个

CodeLength: 10 00 个 CodeLength: 11 02 个 CodeLength: 1202 个

CodeLength: 13 03 个CodeLength: 14 01 个 CodeLength: 1500 个

CodeLength: 16 00 个

FFDA:SOS(Start of Scan,扫描开始)

000C 03 01 00 02 11 03 11 003F 00

length: 12 byte  (2 byte)

颜色分量 ID: 1  (1 byte) (Y) Y Dc HuffmanTreeIndex: 0  (Higher 4bit) Y Ac HuffmanTreeIndex: 0  (Lower 4 bit)

颜色分量 ID:  2  (1 byte) (Uor V) UV Dc HuffmanTreeIndex: 1  (Higher 4 bit) UV Ac HuffmanTreeIndex: 1 (Lower 4 bit)

颜色分量 ID:  3  (1 byte) (Uor V) UV Dc HuffmanTreeIndex: 1  (Higher 4 bit) UV Ac HuffmanTreeIndex: 1  (Lower 4bit)

FFDA: 标记代码 SOS,Start of Scan,扫描开始

数据长度:2 字节,这里是长度为 12 字节。  颜色分量数:1 字节应该和 SOF 中的颜色分量数相同        

颜色分量信息:每个分量对应 3 个字节,第一个字节是颜色分量ID,1,2,3 对应 YUV,

第二个字节高位为直流分量使用的哈夫曼树编号,这里 Y 的直流分量用的是 DC 的第 0 张表,

低四位代表交流分量使用的哈夫曼树编号,这里 Y 的交流分量用的是 AC 的第 0 张表,而两个

色度信号的直流分量都用的是DC 的第 1 张表,交流分量用的是 AC 的第 1 张表. 

最后三个字节为压缩图像数据:

a)谱选择开始    1 字节固定值 0x00

b)谱选择结束   1 字节固定值 0x3F

c)谱选择    1 字节在基本 JPEG 中总为 00

[熵编码数据] 

图片的熵编码数据

FFD9: End of Image,图像结束  结束符,JPEG 文件必须以 EOI 结束

2.JPEG文件解码流程

读入文件的相关信息

初步了解图像数据流的结构

颜色分量单元的内部解码

直流系数的差分编码

反量化 & 反Zig-zag编码

反离散余弦变换

2.1 JPEG 的解码流程

2.1.1 读取文件

2.1.2 解析文件

ü  解析 SOI

ü  解析 APP0  检查标识“JFIF”及版本,得到一些参数

ü  解析 DQT  得到量化表长度(可能包含多张量化表);得到量化表的精度;得到及检查量化表的序号(只能是 0 —— 3);得到量化表内容(64 个数据)

ü  解析 SOF0  得到每个 sample 的比特数、长宽、颜色分量数;得到每个颜色分量的 ID、水平采样因子、垂直采样因子、使用的量化表 序号(与 DQT 中序号对应)

ü  解析 DHT 

ü  得到 Huffman 表的类型(AC、DC)、序号 

ü  依据数据重建 Huffman 表

ü  解析 SOS  得到解析每个颜色分量的 DC、AC 值所使用的 Huffman 表序号(与 DHT 中序号对应)

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

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

ü  对每个宏块进行 Huffman 解码,得到 DCT 系数

ü  对每个宏块的 DCT 系数进行 IDCT,得到 Y、Cb、Cr

ü  遇到 Segment Marker RST 时,清空之前的 DC DCT 系数

2.1.5 解析到 EOI,解码结束

2.1.6 将 Y、Cb、Cr 转化为需要的色彩空间并保存。

2.2使用lookup查找表解huffman码

三个重要的结构体

ü struct  huffman_table

ü struct  component

ü struct  jdec_private

#defineHUFFMAN_BITS_SIZE  256

huffsize[HUFFMAN_BITS_SIZE+1]

huffcode[HUFFMAN_BITS_SIZE+1]

#defineHUFFMAN_HASH_NBITS    9  //程序中查找表码字长度

#defineHUFFMAN_HASH_SIZE (1UL<<HUFFMAN_HASH_NBITS)

struct huffman_table

{

/* 快速查找表,我们可以直接使用huffman_hash_nbits位的符号,如果符号是小于0,那么我们需要查找树表*/

short int lookup[HUFFMAN_HASH_SIZE];

/* 得到解码时读取的符号位数 */

unsigned char code_size[HUFFMAN_HASH_SIZE];

/*一些地方存放的值不在查找表编码,如果256个值编码足以存储所有的值*/

uint16_tslowtable[16-HUFFMAN_HASH_NBITS][256];

};

struct component

{

unsigned int Hfactor;

unsigned int Vfactor;

float *Q_table;              /* 指向所用精度的量化表*/

struct huffman_table *AC_table;

struct huffman_table *DC_table;

short int previous_DC;  /* 之前的DC系数*/

short int DCT[64];         /* DCT 量化表 */

#if SANITY_CHECK

unsigned int cid;

#endif

};

typedef void(*decode_MCU_fct) (struct jdec_private *priv);

typedef void(*convert_colorspace_fct) (struct jdec_private *priv);

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 incrementedeach time */

/* Temp space used after the IDCT to storeeach components */

uint8_t Y[64*4], Cr[64], Cb[64];

jmp_buf jump_state;

/* Internal Pointer use for colorspaceconversion, do not modify it !!! */

uint8_t *plane[COMPONENTS];

};

2.3实验步骤

2.3.1.逐步调试JPEG解码器程序。将输入的JPG文件进行解码,将输出文件保存为可供YUVViewer观看的YUV文件。

2.3.2.  程序调试过程中,应做到:

 理解程序设计的整体框架

 理解三个结构体的设计目的

 struct  huffman_table

 struct  component

 struct  jdec_private

理解在视音频编解码调试中TRACE的目的和含义

会打开和关闭TRACE

会根据自己的要求修改TRACE

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

2.3.4. 输出DC图像并经过huffman统计其概率分布(使用第三个实验中的Huffman编码器)。

2.3.5. 输出某一个AC值图像并统计其概率分布(使用第三个实验中的Huffman编码器)。

部分实验代码如下:

将yuv文件输出:

static voidwrite_yuv(const char *filename, int width, int height, unsigned char**components)

{

FILE *F;

char temp[1024];

/fn add//

snprintf(temp, 1024, "%s.YUV",filename);

F = fopen(temp, "ab");

fwrite(components[0], width, height, F);

fwrite(components[1], width*height/4,1, F);

fwrite(components[2], width*height/4,1, F);

fclose(F);

}

实验所用JPEG图像如下

得到的yuv图像如下

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

tinyjpeg.c,一共用到以下4个函数:

static int parse_DQT(struct jdec_private *priv, constunsigned char *stream)

{

int qi;

float *table;

const unsigned char *dqt_block_end;

#if TRACE

fprintf(p_trace,"> DQTmarker\n");

fflush(p_trace);

#endif

dqt_block_end = stream + be16_to_cpu(stream);

stream += 2;    /*Skip length */

while (stream < dqt_block_end)

{

qi = *stream++;

#if SANITY_CHECK

if (qi>>4)

snprintf(error_string, sizeof(error_string),"16 bits quantizationtable is not supported\n");

if (qi>4)

snprintf(error_string, sizeof(error_string),"No more 4 quantizationtable is supported (got %d)\n", qi);

#endif

table = priv->Q_tables[qi];

build_quantization_table(table, stream);

stream += 64;

}

#if TRACE

 fprintf(p_trace,"quantization table[%d]\n",qi);//输出量化表序号

 fflush(p_trace);

#endif

……

return 0;

}

static void build_quantization_table(float *qtable,const unsigned char *ref_table)

{

int i, j;

static const double aanscalefactor[8] = {

1.0, 1.387039845, 1.306562965,1.175875602,

1.0, 0.785694958, 0.541196100, 0.275899379

};

const unsigned char *zz = zigzag;

for (i=0; i<8; i++) {

for (j=0; j<8; j++) {

*qtable++ = ref_table[*zz++] *aanscalefactor[i] * aanscalefactor[j];

#if TRACE

                      fprintf(p_trace,"%d\t",ref_table[*zz]);

                      fflush(p_trace);

                      if(j==7) //以8*8矩阵形式输出量化表

                      {fprintf(p_trace,"\n");

                      fflush(p_trace);}

       #endif

}

}

}

static int parse_DHT(struct jdec_private *priv, constunsigned char *stream)

{

unsigned int count, i;

unsigned char huff_bits[17];

int length, index;

length = be16_to_cpu(stream) - 2;

stream += 2;    /*Skip length */

#if TRACE

fprintf(p_trace,"> DHT marker(length=%d)\n", length);

fflush(p_trace);

#endif

while (length>0) {

index = *stream++;

/* We need to calculate the number ofbytes 'vals' will takes */

huff_bits[0] = 0;

count = 0;

for (i=1; i<17; i++) {

huff_bits[i] = *stream++;

count += huff_bits[i];

}

#if SANITY_CHECK

if (count >= HUFFMAN_BITS_SIZE)

snprintf(error_string,sizeof(error_string),"No more than %d bytes is allowed to describe ahuffman table", HUFFMAN_BITS_SIZE);

if ( (index &0xf) >=HUFFMAN_TABLES)

snprintf(error_string,sizeof(error_string),"No more than %d Huffman tables is supported (got%d)\n", HUFFMAN_TABLES, index&0xf);

#if TRACE

    fprintf(p_trace,"Huffman table %s[%d] length=%d\n",

(index&0xf0)?"AC":"DC",index&0xf, count);//输出Huffman表类型,长度,序号

        fflush(p_trace);

#endif

#endif

if (index & 0xf0 )

build_huffman_table(huff_bits, stream,&priv->HTAC[index&0xf]);

else

build_huffman_table(huff_bits, stream,&priv->HTDC[index&0xf]);

length -= 1;

length -= 16;

length -= count;

stream += count;

}

#if TRACE

fprintf(p_trace,"< DHTmarker\n");

fflush(p_trace);

#endif

return 0;

}

static void build_huffman_table(const unsigned char*bits, const unsigned char *vals, struct huffman_table *table)

{

unsigned int i, j, code, code_size, val,nbits;

unsigned char huffsize[HUFFMAN_BITS_SIZE+1],*hz;

unsigned int huffcode[HUFFMAN_BITS_SIZE+1],*hc;

int next_free_entry;

/*

* Build a temp array

*  huffsize[X] => numbers of bits to write vals[X]

*/

hz = huffsize;

for (i=1; i<=16; i++)

{

for (j=1; j<=bits[i]; j++)

*hz++ = i;

}

*hz = 0;

memset(table->lookup, 0xff,sizeof(table->lookup));

for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++)

table->slowtable[i][0] = 0;

/* Build a temp array

*   huffcode[X] => code used to write vals[X]

*/

code = 0;

hc = huffcode;

hz = huffsize;

nbits = *hz;

while (*hz)

{

while (*hz == nbits)

{

*hc++ = code++;

hz++;

}

code <<= 1;

nbits++;

}

/*

* Build the lookup table, and the slowtableif needed.

*/

next_free_entry = -1;

for (i=0; huffsize[i]; i++)

{

val = vals[i];

code = huffcode[i];

code_size = huffsize[i];

#ifTRACE

    fprintf(p_trace,"val=%2.2x code=%8.8x codesize=%2.2d\n", val,code, code_size);//输出Huffman码表

        fflush(p_trace);

    #endif

table->code_size[val] = code_size;

if (code_size <= HUFFMAN_HASH_NBITS)

{

int repeat =1UL<<(HUFFMAN_HASH_NBITS - code_size);

code <<= HUFFMAN_HASH_NBITS - code_size;

while ( repeat-- )

table->lookup[code++] = val;

}

else

{

/* Perhaps sorting the array will be anoptimization */

uint16_t *slowtable =table->slowtable[code_size-HUFFMAN_HASH_NBITS-1];

while(slowtable[0])

slowtable+=2;

slowtable[0] = code;

slowtable[1] = val;

slowtable[2] = 0;

/* TODO: NEED TO CHECK FOR AN OVERFLOW OFTHE TABLE */

}

}

}

输出的4张Huffman码表如下(省略部分):

两张量化表输出结果如下:

输出DC图像并经过huffman统计其概率分布(使用第三个实验中的Huffman编码器)。

在头文件中声明文件,在main函数中打开关闭文件,并在 tinyjpeg_decode.c文件中的函数作如下添加(加粗部分):

int tinyjpeg_decode(struct jdec_private *priv, int pixfmt)

{

……….

unsignedchar  DCimage;

  unsigned charACimage;

  float DC;

  float AC;

……………

/* Just the decode the image by macroblock(size is 8x8, 8x16, or 16x16) */

for (y=0; y <priv->height/ystride_by_mcu; y++)

{

//trace("Decoding row %d\n", y);

priv->plane[0] = priv->components[0]+ (y * bytes_per_blocklines[0]);

priv->plane[1] = priv->components[1]+ (y * bytes_per_blocklines[1]);

priv->plane[2] = priv->components[2]+ (y * bytes_per_blocklines[2]);

for (x=0; x < priv->width;x+=xstride_by_mcu)

{

decode_MCU(priv);

convert_to_pixfmt(priv);

priv->plane[0] +=bytes_per_mcu[0];

priv->plane[1] +=bytes_per_mcu[1];

priv->plane[2] +=bytes_per_mcu[2];

if (priv->restarts_to_go>0)

{

priv->restarts_to_go--;

if (priv->restarts_to_go == 0)

{

priv->stream -=(priv->nbits_in_reservoir/8);

resync(priv);

if (find_next_rst_marker(priv) < 0)

return -1;

}

}

DC=(priv->component_infos->DCT[0]+512)/4;

//DC系数的取值在-512~512之间,需要将其转化至0-255之间显示。

              DCimage=(unsigned char)DC;

              fwrite(&DCimage,1,1,DCFILE);//在每一个块中循环输出DC系数

              AC=(priv->component_infos->DCT[1]+128);

//AC系数的取值在-128~128之间,需要将其转化至0-255之间显示。

              ACimage=(unsignedchar)AC;

              fwrite(&ACimage,1,1,ACFILE);

}

}

……………….

return 0;

}

输出某一个AC值图像并统计其概率分布(使用第三个实验中的Huffman编码器)。

在此采用8*8宏块扫描,每一个宏块输出一个DC值,输出一个AC值,在此输出AC[1],所以输出的AC与DC图像宽高都为原来的1/8;

数据压缩实验5-JEPG解码相关推荐

  1. 【数据压缩-实验5】JPEG原理分析及JPEG解码器的调试

    目录 JEPG原理 简述 优点 缺点 JPEG文件格式 常用标记码 编解码原理 编码原理 Level offset-零偏置 DCT变换 量化 DC系数差分编码 AC系数的之字形扫描+游程编码 解码原理 ...

  2. 数据压缩实验四--DPCM

    数据压缩实验四--DPCM 实验原理 DPCM编解码原理 PSNR计算压缩质量 实验代码 DPCM.cpp main.cpp DPCM.h 实验步骤 实验图片的准备 命令参数 图像质量比较 8比特量化 ...

  3. 【数据压缩实验六--MPEG】

    数据压缩实验六--MPEG 感知音频编码设计思想 多相滤波器组 心理声学模型 临界频带 掩蔽值计算 心理声学模型I的具体过程 码率分配 LayerI LayerII 实验过程 输出音频的采样率和目标码 ...

  4. 数据压缩实验一:yuv转rgb格式实验报告

    数据压缩实验一:yuv转rgb格式实验报告 一:实验基本原理 yuv转rgb格式转换公式: R=Y+1.4020*(V-128) G=Y-0.3441*(U-128)-0.7141*(V-128) B ...

  5. 数据压缩实验一实验报告

    数据压缩实验一实验报告 1.实验原理 YUV到RGB的转换算法为 R=Y+1.4075(V−128) R = Y + 1.4075(V - 128) G=Y+0.3455(U−128)−0.7169( ...

  6. 数据压缩实验五:JPEG文件解码实验分析

    一:实验原理 1.JPEG编码原理 JPEG 是Joint Photographic Experts Group(联合图像专家小组)的缩写,是第一个国际图像压缩标准. .jpeg/.jpg是最常用的图 ...

  7. 数据压缩 实验三 Huffman编解码算法实现与压缩效率分析

    实验目的 掌握Huffman编解码实现的数据结构和实现框架, 进一步熟练使用C编程语言, 并完成压缩效率的分析. 实验原理 1.本实验中Huffman编码算法 (1)将文件以ASCII字符流的形式读入 ...

  8. 数据压缩原理实验4_DPCM编解码

    一.实验原理 DPCM编解码原理 DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统.而预测编码就是根据过去的信号样值来预测下一个信号样值,并将预测值与现实样值得差值进行量化.编码后进行数字信 ...

  9. 数据压缩实验三--Huffman编解码及压缩率的比较

    一,Huffman码 1 Huffman 编码 Huffman Coding (霍夫曼编码)是一种无失真编码的编码方式,Huffman编码是可变字长编码(VLC)的一种. Huffman 编码基于信源 ...

最新文章

  1. 执行公式_法院诉讼费、保全费、执行费速算公式
  2. socket阻塞和非阻塞的区别
  3. 遥想当年年纪小,追风逐浪没烦恼
  4. 使用oracle 的 PL/Sql 定时执行一个存储过程
  5. 超乎想象,数据揭示自学成才的码农为何备受青睐
  6. epoll nio区别_大厂面试系列(二)::NIO和Netty
  7. python gevent模块 下载_Python中的多任务,并行,并发,多线程,多进程,协程区别...
  8. ecshop操作数据库类
  9. The following tasks did not complete: first Did you forget to signal async completion?
  10. 使用java concurrent处理异步加载图片功能
  11. webrtc 渲染_WebRTC 开发(六)摄像头采集与视频渲染分析
  12. c++new时赋初值_如何把C++的源代码改写成C代码?
  13. 伪元素::selection -- CSS ::selection 伪元素,定义用户鼠标已选择内容的样式
  14. 白盒测试的学习之路----(五)TestNG的参数分离
  15. c语言奇偶校验完整程序,求助 奇偶校验的C语言编程
  16. 若计算机系统有120个终端,概率论答案 - 李贤平版 - 第五章
  17. 震惊~~飞流android版使用体验!!
  18. iOS 判断是否为iPhoneX以上设备
  19. [论文阅读] Facial Expression Recognition Using Residual Masking Network
  20. 图像分类之:经典机器学习 Battle 深度学习

热门文章

  1. APICloud和海马玩模拟器结合调试手机页面
  2. cass简码大全_cass简码实体对照表
  3. office 打开wps乱_为什么word文档用wps打开,格式乱了
  4. 【超详细】MySQL零基础入门实战
  5. 用utraISO刻录windows10系统并用U盘安装,用easyBCD安装ubuntu18.04
  6. 四层PCB核心板制作6——BGA引脚扇出与电路扇孔
  7. Python批量识别PDF文件格式发票信息并生成Excel表格
  8. OpenCV 文字检测与识别模块
  9. 苏州计算机岗前培训,我院召开2018年新职工岗前培训动员大会
  10. x64dbg调试器使用