本篇是该系列的第四篇,主要介绍霍夫曼解码相关内容。

承接上篇,文件头解析完毕后,就进入了编码数据区域,即SOS的tag后的区域,也是图片数据量的大头所在。

1. 解码过程规则描述

a)从此颜色分量单元数据流的起点开始一位一位的读入,直到读入的编码与该分量直流哈夫曼树的某个码字(叶子结点)一致,然后用直流哈夫曼树

查得该码字对应的权值。权值(共8位)表示该直流分量数值的二进制位数,也就是接下来需要读入的位数。

b)继续读入位数据,直到读入的编码与该分量交流哈夫曼树的某个码字(叶子结点)一致,然后用交流哈夫曼树查得该码字对应的权值。权值的高4位

表示当前数值前面有多少个连续的零,低4 位表示该交流分量数值的二进制位数,也就是接下来需要读入的位数。

c)不断重复步骤b,直到满足交流分量数据结束的条件。

而结束条件有两个,只要满足其中一个即可:

①当读入码字的权值为零,表示往后的交流变量全部为零;
②已经读入63个交流分量。

2. 待处理的数据区域

  上面的规则描述过于抽象,需要一个例子来实战说明,仍使用那张animal_park.jpg的图片。

  其二进制数据显示如下(FFDA所代表的SOS之后深色标注区域):

  截取到的二进制数据为:F9 96 8B FA 71 EA 5B 24 B5 ...

3. 准备好霍夫曼表

  先列出四张霍夫曼表——DC0,AC0, DC1,AC1,待后面查找使用。

  DC0——Y分量的直流部分

  AC0——Y分量的交流部分(表太长,没列全)

  DC1——UV分量的直流部分

  AC1——UV分量的交流部分

4. 解码步骤

  这是难点所在,解码的过程其实就是霍夫曼树的查找过程。mcu单元内部使用了RLE行程编码和霍夫曼编码来压缩数据。

  例子:F9 96 8B FA 71 EA 5B 24 B5。。。

  对应的二进制位展开:1111 1001, 1001 0110, 1000 1011, 1111 1010, 0111 0001, 1110 1010, 0101 1011, 0010 0100, 1011 0101。。。

step1. 先读入若干位与DC0表的Code进行匹配。

读取2位的11时,  无匹配的Code,因为2位宽的Code只有0b00和0b01

3位的111        无                              3                           0b100,0b101和0b110。

4位的1111      无                              4                            0b1110。

5位的11111    无                              5                            0b11110。

6位的111110  有                              6                            0b111110,恰好匹配!其对应的CodeVal为0x7

step2. 利用上面得到的CodeVal进行拆分,并读取后面若干位。
  0x7=0x07,高四位为0,低四位为7,则再读取后面的7位二进制,为:01, 1001 0。
  后面读取的值,这样算:如果开头为1则为正数,如果开头为0,则为负数,然后对各位求反得到数值,即可。

  01, 1001 0这个值,由于开头为0,则为负数,多少呢?取反得到:10, 01101 = 0x4D = 77,最后得到最终值为:-77。

step3. 通过上面两步骤的第一次扫描,得到的为Y分量的DC值,后面还需经过63次扫描得到剩余的AC值(一般扫描几次就结束了)。

  上面DC值标记为-77。

step4. 继续通过类似step1和step2来取得AC值,注意要查找AC0表。

  读取5位的110, 10时,有匹配的Code:0b11010=0x1a,其对应的CodeVal=0x04;
  取得后四位的值——4,表示还需读取的二进制位数量,来表示真正的信源值——0b0010,经(step2中描述)变换后值为-13;
  那么可以RLE标记为(0,-13),其中0来自于CodeVal的高4位,-13为另读入的数据值。可也记为key-val对。

step5. 重复step4的操作,直到得到(0,0)(位置为5B那个字节的最高四位)。

  后面的依次为:

Code                                CodeVal          RLE_val        RLE

11, 1111 1010(0x3FA)         0x34            0111(-8)         (3, -8)

00                                        0x1              0 (-1)              (0, -1)

1, 1110 10(0x7A)                 0x71            1(1)                (7, 1)

00                                          0x1             1(1)                (0, 1)

01                                          0x0              --                   (0, 0)  -> 结束于5B的高4位

step6. 通过step1-step5的扫描,得到数据:-77, (0, -13), (3, -8),(0, -1),(7, 1), (0, 1), (0, 0)

step7. step1到step6结束后,表示一个mcu的霍夫曼解码结束。

  RLE中的(m,n),m表示前面填充0的个数,n表示实际值。

  其解码结果如下:

JPEG解码——(4)霍夫曼解码的更多相关文章

  1. c++实现哈夫曼树,哈夫曼编码,哈夫曼解码(字符串去重,并统计频率)

    #include <iostream> #include <iomanip> #include <string> #include <cstdlib> ...

  2. 赫夫曼解码(day17)

    思路: 传入map(字节与对应字节出现的次数)和最后生成的要传送的字节.将他们先转换成对应的二进制字节,再转换成原来的字符串. 代码: 12345678910111213141516171819202 ...

  3. C# 霍夫曼二叉树压缩算法实现

    知道有的人比较懒,直接贴全部代码. 一开始一次性Code完了压缩部分代码.只调试了2,3次就成功了. 一次性写150行代码,没遇到什么bug的感觉还是蛮爽的. 写解压代码,才发现压缩代码有些细节问题. ...

  4. 霍夫曼编码(Huffman Coding)

    霍夫曼编码(Huffman Coding)是一种编码方法,霍夫曼编码是可变字长编码(VLC)的一种. 霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符 ...

  5. Java数据结构(十二)—— 霍夫曼树及霍夫曼编码

    霍夫曼树 基本介绍和创建 基本介绍 又称哈夫曼树,赫夫曼树 给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称为最优二叉树 霍夫曼树是带权路径长度最短的树,权值较 ...

  6. 赫夫曼\哈夫曼\霍夫曼编码 (Huffman Tree)

    哈夫曼树 给定n个权值作为n的叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree).哈夫曼树是带权路径长度最短的树,权值较大的结点离 ...

  7. 基于python的二元霍夫曼编码译码详细设计

    一.设计题目 对一幅BMP格式的灰度图像(个人证件照片)进行二元霍夫曼编码和译码 二.算法设计 (1)二元霍夫曼编码: ①:图像灰度处理: 利用python的PIL自带的灰度图像转换函数,首先将彩色图 ...

  8. word2vec 中的数学原理二 预备知识 霍夫曼树

    主要参考:    word2vec 中的数学原理详解                 自己动手写 word2vec 编码的话,根是不记录在编码中的 这一篇主要讲的就是霍夫曼树(最优二叉树)和编码.  ...

  9. CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树

    http://codeforces.com/contest/462 A:Appleman and Easy Task 要求是否全部的字符都挨着偶数个'o' #include <cstdio> ...

随机推荐

  1. 一块网卡配2IP地址

    我们知道在Linux下网卡被称为eth0,eth1,eth2.....,所有网卡的配置文件都存储在 /etc/sysconfig/network-script/下,文件名是以ifcfg-eth0,if ...

  2. 使用两个FIFO完成流水操作

    一.设计目标 写一个FIFO控制器,控制器里有两个FIFO,输入的数据由串行接收模块(uart_rx_module)送来,一共有86行86列的数据,按0.1.2行,1.2.3行,直到最后83.84.8 ...

  3. 织梦dedecms自由列表的"不使用目录默认主页"错误修正

    站长用织梦做站时常常发现织梦自由列表有个致命的问题: 即修改"不使用目录默认主页"就永远不会自己勾选啦 打开这个文件 makehtml_freelist_action.php 搜索 ...

  4. Flink-v1.12官方网站翻译-P023-The Broadcast State Pattern

    广播状态模式 在本节中,您将了解如何在实践中使用广播状态.请参考状态流处理,了解状态流处理背后的概念. 提供的API 为了展示所提供的API,我们将在介绍它们的全部功能之前先举一个例子.作为我们的运行 ...

  5. DolphinScheduler1.3.2源码分析(二)搭建源码环境以及启动项目

    前置依赖组件安装 找一台服务器,或者本地的虚拟机,然后在服务器上安装好jdk,zookeeper,mysql. 1.源码调试环境搭建 源码环境搭建可以参考DolphinScheduler官方网站的开发 ...

  6. 四十五:漏洞发现-API接口服务之漏洞探针类型利用修复

    接口服务类安全测试 根据前期信息收集针对目标端口服务类探针后进行的安全测试,主要涉及攻击方法:口令安全,WEB类漏洞,版本漏洞等,其中产生的危害可大可小,属于端口服务/第三方服务类安全测试.一般在已知 ...

  7. Notepad++ 替换 CRLF 为 LF

    对于文件中每一行的结尾符号,Windows 下默认为 CRLF,而 Unix 下默认为 LF. 所以经常会有这样的情况发生:在 Windows 系统下编辑的文件放在 Unix 下不能正常执行,比如 b ...

  8. Grakn Forces 2020

    比赛链接:https://codeforces.com/contest/1408 A. Circle Coloring 题意 给出三个长为 $n$ 的序列 $a,b,c$,对于每个 $i$,$a_i ...

  9. zjnu1709 UZASTOPNI (bitset,树形dp)

    Description Petar is throwing a birthday party and he decided to invite some of the employees of his ...

  10. 吉哥系列故事――恨7不成妻 HDU - 4507

    题目: 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 7+7=7*2 ...