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也依次类推得到相应的数据值。

JPEG中Huffman解码实例讲解相关推荐

  1. python 安卓模拟点击_python模拟点击在ios中实现的实例讲解

    我们都知道因为操作系统的不同,很多游戏区分为安卓和苹果两个版本.那么之前学会python模拟点击的小伙伴开始担心,如果手机是ios版本那还能使用吗?这个问题小编进行了测试,小伙伴们完全不用忧虑ios版 ...

  2. python 图像处理与识别书籍_Python图像处理之识别图像中的文字(实例讲解)

    ①安装PIL:pip install Pillow(之前的博客中有写过) ②安装pytesser3:pip install pytesser3 ③安装pytesseract:pip install p ...

  3. python去除图片上的文字_Python图像处理之识别图像中的文字(实例讲解)

    ①安装PIL:pip install Pillow(之前的博客中有写过) ②安装pytesser3:pip install pytesser3 ③安装pytesseract:pip install p ...

  4. python实现安卓点击_python模拟点击在ios中实现的实例讲解

    我们都知道因为操作系统的不同,很多游戏区分为安卓和苹果两个版本.那么之前学会python模拟点击的小伙伴开始担心,如果手机是ios版本那还能使用吗?这个问题小编进行了测试,小伙伴们完全不用忧虑ios版 ...

  5. python模拟点击屏幕ios_python模拟点击在ios中实现的实例讲解

    我们都知道因为操作系统的不同,很多游戏区分为安卓和苹果两个版本.那么之前学会python模拟点击的小伙伴开始担心,如果手机是ios版本那还能使用吗?这个问题小编进行了测试,小伙伴们完全不用忧虑ios版 ...

  6. 如何通过js获取html文本框中的值,js与jquery获取input输入框中的值实例讲解

    如何用javascript获取input输入框中的值,js/jq通过name.id.class获取input输入框中的value 先准备一段 HTML 一.jquery获取input文本框中的值 通过 ...

  7. [原创]桓泽学音频编解码(7):MP3 和 AAC 中huffman解码原理,优化设计与参考代码中实现...

    1 不同标准中的huffman解码原理 1.1标准MP3的huffman解码原理 在MP3即mpeg-1 audio标准中,无噪声编码模块的输入是一组576个己量化的频谱数据.无噪声编码首先对频谱进行 ...

  8. 《GO语言圣经》:Bit数组实例讲解

    <GO语言圣经>第六章方法中Bit数组实例讲解,与课后习题答案. 书中介绍了关于方法的语法,在最后给出一个实例--Bit数组实现集合这种数据结构. 目的 实现集合的数据结构,并能够做集合的 ...

  9. 实例讲解Linux系统中硬链接与软链接的创建

    导读 Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link).默认情况下,ln命令产生硬链接.硬链接与软链接的区别从根本上要从Inode节点说 ...

  10. java中删除sqlite数据库语句_sqlite数据库的介绍与java操作sqlite的实例讲解

    sqlite数据库的介绍与java操作sqlite的实例讲解 发布时间:2020-10-03 05:40:34 来源:脚本之家 阅读:92 作者:Lee_Tech sqlite是啥? 1.一种轻型数据 ...

最新文章

  1. [Big Data - Kafka] kafka学习笔记:知识点整理
  2. IOS之代理文字点击变大变小
  3. 过程(栈帧结构是干货)
  4. SumatraPDF安装包
  5. 计算机电子书 2019 BiliDrive 备份
  6. 30款免费3D建模软件,总有一款适合你!
  7. Scc Puzzle
  8. unity 彩带粒子_unity游戏缤纷五彩纸屑粒子特效Confetti FX 1.0
  9. java 提高随机数效率_抢拍神器的关键:优化提升Java线程局部随机数ThreadLocalRandom高并发技巧 - alidg...
  10. Springboot面试杀手锏-自动配置原理
  11. 每日一狗 · 比利牛斯山犬
  12. Pycharm中,pyqt5.11.1的Qt assistant显示
  13. 我的世界java笔刷指令_原版创世神刷子工具命令方块指令分享
  14. delphi控件切图界面闪烁_8、控件系列之_加载占位图+页面指示器
  15. 一文速览全球央行数字货币最新进展
  16. VNode――Beijing OpenParty晓风归雁后记
  17. html浏览器标题闪动,如何实现网页标题的闪动提示
  18. python实现批量识别图片文字,生成对应的txt文件
  19. SII-Slave Information Interface
  20. 如何通过VB合并Excel单元格以及设置Excel行高?VB创建Excel表格,合并单元格,生成图形等操作

热门文章

  1. python教程55--D-Tale使用介绍
  2. 基于Harry Potter的数据可视化
  3. OSChina 周三乱弹 —— 我在 if 里,你却在 else
  4. 通过Python获取维基百科中概念词条的维基信息
  5. C++ “system“的详解
  6. 中级财务管理机考计算机,2017年中级会计师考试无纸化机考技巧
  7. 【博客5】缤果LabView串口调试助手V2.0 (高级篇)
  8. java的inputbox_InputBox函数的使用方法
  9. Word如何转PDF
  10. 产业AI公司的简单调研