JPEG中Huffman解码实例讲解

DHT Huffuman表格式

--------------------------------------------------------------------------
名称      字节数     值       说明
--------------------------------------------------------------------------
段标识       1        FF
段类型       1        C4
段长度       2                    其值=19+n(当只有一个HT表时)
  (以下为段内容)
HT信息      1                    0-3位:HT号
                                             4位: HT类型, 0=DC表,1=AC表
                 5-7位:必须=0
HT位表      16                  这16个数的和应该≤256
HT值表       n                   n=表头16个数的和
--------------------------------------------------------------------------

读取Huffman

FF C4 01 A2 00 00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00 00 01 02 03 04 05 06 07 08 09 0A 0B

FF C4:Huffman表识别码

01 A2:DHT表长度(01~0B的字节数)

00:4bit=0,为DC表;低3bit=0,HT号为0;表示DC直流0号表

00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00:DHT不同bits位数的码字数量,数据之和表示叶子节点数目:1+5+1+1+1+1+1+1 = 12;

00 01 02 03 04 05 06 07 08 09 0A 0B:编码内容,即每个叶子节点下的编码值

构建Huffman

读取到Huffman表的数据之后,就需要构建Huffman树了。其具体规则如下:

  (a)第一个编码的数字必定为0;如果第一个编码的位数为1,就被编码为0;如果第一个编码的位数为2,就被编码为00;如果第一个编码的位数为3,就被编码为000。。。

  (b)从第二个编码开始,如果它和它前面编码具有相同的位数,则当前编码是它前面的编码加1;如果它的编码位数比它前面的编码位数大,则当前编码时它前面的编码加1之后再在后面添加若干个0,直到满足编码位数的长度为止。

还是以上面的数据00 01 05 01 01 01 01 01 01 00 00 00 00 00 00 00为例:

第1个字节00表示没有位数为1的编码;

第2个字节01表示位数为2的编码有2个;由于没有位数为1的编码,因此这里位数为2的编码中的第一个为00;

第3个字节05表示位数为3的编码有5个;因此,这里位数为3的编码中的第一个为00+1=01,然后添加1个“0”,得到010;位数为3的编码中的第二个为010+1=011;第三个为011+1=100;第四个为100+1=101;第五个为101+1=110;

第4个字节01表示位数为4的编码有1个;因此,这里位数为4的编码中的第一个为110+1=111,然后添加1个“0”,得到1110;

第5个字节01表示位数为5的编码有1个;因此,这里位数为5的编码中的第一个为1110+1=1111,然后添加1个“0”,得到11110;

依次类推,得到如下Huffman树,表1:

Y(luminance亮度)-DC

序号(bits位数)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

相同Bits位的个数

0

1

5

1

1

1

1

1

1

0

0

0

0

0

0

0

说明

没有位数为1的编码

1个2bits

5个3bits

1个4bits

1个5bits

1个6bits

1个7bits

1个8bits

1个9bits

没有位数为10的编码

没有位数为11的编码

没有位数为12的编码

没有位数为13的编码

没有位数为14的编码

没有位数为15的编码

没有位数为16的编码

码字(二进制)

00

(00+1)<<1

==>

010

011

100

101

110

(110+1)<<1

==>

1110

(1110+1)<<1

==>

1111 0

(11110+1)<<1

==>

1111 10

(111110+1)<<1

==>

1111 110

(1111110+1)<<1

==>

1111 1110

(11111110+1)<<1

==>

1111 1111 0

根据Huffman树,建立DHT权值与实际保存数据与DCT量化后数据 表2,查此表可以对jpeg做解码:

序号

Bits位数

码字长度

码字

DHT权值

Size(数值bits宽度)

Additionnal Bits

(实际保存的数据)

DC-value(DCT量化后的数据)

1

2bits

2

00

0x0

0x00

0

0

2

3bits

3

010

0x2

0x01

1

0

1

-1

1

3

3

011

0x3

0x02

2

00,01

10,11

-3,-2

2,3

4

3

100

0x4

0x03

3

000,001,010,011

100,101,110,111

-7,-6,-5,-4

4,5,6,7

5

3

101

0x5

0x04

4

0000,…,0111

1000,…,1111

-15,…,-8

8,…,15

6

3

110

0x6

0x05

5

0000 0,…,01111

1000 0,…,11111

-31,…,-16

16,…,31

7

4bits

4

1110

0xE

0x06

6

0000 00,…,011111

1000 00,…,111111

-64,…,-32

32,…,64

8

5bits

5

1111 0

0x1E

0x07

7

0000 000,…

…,1111 111

-127,…,-64

64,…,127

9

6bits

6

1111 10

0x3E

0x08

8

0000 0000,…

…,1111 1111

-255,…,-128

128,…,255

A

7bits

7

1111 110

0x7E

0x09

9

0000 0000 0,…

…,1111 1111 1

-511,…,-256

256,…,511

B

8bits

8

1111 1111

0xFE

0x0A

A

0000 0000 00,…

…,1111 1111 11

-1023,…,-512

512,…,1023

C

9bits

9

1111 1111 0

0x1FE

0x0B

B

0000 0000 000,…

…,1111 1111 111

-2047,…,-1024

1024,…,2047

高4bits:保留零的个数

低4bits:接着的数据位长

0n

负数

正数

-(1<<(n+1)-1) ~ -(1<<n)

(1<<n) ~ (1<<(n+1)-1)

DHT权值表中,高4bit表示零保留的个数,低4bit表示接着的数据位长。

Huffman:DC实际值 -> Size[编码长度] -> 权值 -> bitstring{.Len;   .value;}

Encode: DC实际值 -> DQT量化 -> ZigZag扫描 ->(Y:DPCM编码,CbCr)->  huffman -> write

根据Huffman系数,或者读取Huffman系数,重建Huffman表:

static BYTE std_dc_luminance_nrcodes[17]={0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};

static BYTE std_dc_luminance_values[12]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

static BYTE std_dc_chrominance_nrcodes[17]={0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};

static BYTE std_dc_chrominance_values[12]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

static BYTE std_ac_luminance_nrcodes[17]={0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d };

static BYTE std_ac_luminance_values[162]=

  { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa };

static BYTE std_ac_chrominance_nrcodes[17]={0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};

static BYTE std_ac_chrominance_values[162]=

{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa };

依照上述重建Huffman表的方法,可得:

DHT-Y-DC

DHT-Y-AC

DHT-CbCr-DC

DHT-CbCr-AC

序号

相同Bits位数的:码字个数

相同bits位数:码字起始

相同bits位数:码字结束

相同Bits位数的:码字个数

相同bits位数:码字起始

相同bits位数:码字结束

相同Bits位数的:码字个数

相同bits位数:码字起始

相同bits位数:码字结束

相同Bits位数的:码字个数

相同bits位数:码字起始

相同bits位数:码字结束

1 

0

0

0

0

0

0

0

0

0

0

0

0

2

1

0

0

2

0

0x1

3

0

0x2

2

0

0x1

3

5

0x2

0x6

1

0x4

0x4

1

0x6

0x6

1

0x4

0x4

4

1

0xE

0xE

3

0xA

0xC

1

0xE

0xE

2

0xA

0xB

5

1

0x1E

0x1E

3

0x1A

0x1C

1

0x1E

0x1E

4

0x18

0x1B

6

1

0x3E

0x3E

2

0x3A

0x3B

1

0x3E

0x3E

4

0x38

0x3B

7

1

0x7E

0x7E

4

0x78

0x7B

1

0x7E

0x7E

3

0x78

0x7A

8

1

0xFE

0xFE

3

0xF8

0xFA

1

0xFE

0xFE

4

0xF6

0xF9

9

1

0x1FE

0x1FE

5

0x1F6

0x1FA

1

0x1FE

0x1FE

7

0x1F4

0x1FA

10

0

0

0

5

0x3F6

0x3FA

1

0x3FE

0x3FE

5

0x3F6

0x3FA

11

0

0

0

4

0x7F6

0x7F9

1

0x7FE

0x7FE

4

0x7F6

0x7F9

12

0

0

0

4

0xFF4

0xFF7

0

0

0

4

0xFF4

0xFF7

13

0

0

0

0

0

0

0

0

0

0

0

0

14

0

0

0

0

0

0

0

0

0

1

0x3FE0

 0x3FE0

15

0

0

0

1

0x7FC0

0x7FC0

0

0

0

2

0x7FC2

0x7FC3

此时,得到Huffman的size(码字bit位数)与code(相同bit位数的编码值)表。由此可进行Huffman的解码过程:

1)        将待解码数据转换成二进制的数据流;

2)        遍历表Huffman_size、Huffman_code,从待解码二进制数据流中寻找到长度与Huffman_size相等,内容与Huffman_code相等的二进制数据段,并记录下表的ID(即:是在表的第几个数据中寻找到的);

3)        将此ID 值除以16,其商为cnt(指之前有cnt个0),其余数即为取数长度Len;

4)        在二进制的数据流中,从与Huffman_code相同的数据流后,开始取数,取数长度为第3步得到的Len,假设取得的数据为data;

5)        根据data的值,转换得到相应的解码数据de_data。(根据最高位,为1则为相应的数,为0则取反后的负值。例,data=100,则解码后数据de_data值为4;data=010,解码后数据de_data为-5;

6)        写上de_data的值,并在前面添加上cnt个0。至此,解码完成。

示例数据讲解

 长度01 A2后面的字节: 00 表示Y-DC, tablenum=0; 10表示Y-AC, tablenum=1;01表示Cb-DC,tablenum=2;11表示Cb-AC,tablenum=3;

后面的数据依次是bits位数的个数表,bits位数表(码表);

根据这个重建Huffman表,得到size与code表;

DHT后面是SOS数据,实际的数据流从E2 E8 A2 8A F9 93 F7 开始

Huffman解码时,每次读取32bit数据,此次前4字节数据为E2 E8 A2 8A,转换城二进制数据为:

1110 0010 1110 1000 1010 0010 10000 1010

首次编码的数据一定是Y-DC,所以这里可跟表2匹配:匹配二进制数据的长度与Huffman_size相等,内容与Huffman_code相等的二进制数据段,记录下Huffman的ID号,此时匹配上的1110, 码字长度为4,对应的DHT权值为6,即后面需要读取6 bits数据(001011)作为该组数据,对应的实际DCT量化后的数据值为-53。【(001011对应10进制数据为11) 故数据为:11- (1<<6)  ==> -53 】,此次计算共用的bit位数为4+6 = 10,所以下一组数据从偏移10bits开始,依次类推,可得出下如下数据:

1110 0010 11    101 0001    010 0     010 1     0000 1010

二进制数据 1110 0010 11  101 0001 010 0 010 1 00 00

1010 后面读byte数据,补足32bit,再做Huffman解码,如:

1010 (F9)(93) (F7)

...
实际数值 -53 -14 -1 1 0 0 ...
说明 4bits码字,6bits数据 3bits码字,4bits数据 3bits码字,1bits数据 3bits码字,1bits数据 2bits数据 ...

当数据长度不够时,可从后面读取byte的数据以填充,以补足32 bits数据做Huffman解码。 

 Y-AC,Cb-DC,Cb-AC也依次类推得到相应的数据值。

猜你喜欢

转载自blog.csdn.net/u010192735/article/details/120860826