【原创】JPEG图像密写研究(二) 哈夫曼树的建立
【原创】记录自己研究的过程,仅供参考,欢迎讨论。。。
在根据JPEG图像文件结构读取完文件后,提取出其中DHT段,利用其中内容建立哈夫曼树,便于之后译码工作。这里需要注意的是文件中的哈夫曼表数量不固定,可能为一个,可能为四个,即是可能需要建立多个哈夫曼树,要注意数据选择,不要选择了其他树的数据。
下面为DHT段内容:
DHT,Difine Huffman Table,定义哈夫曼表
标记代码 2字节 固定值0xFFC4
包含2个具体字段:
①数据长度 2字节 字段①和多个字段②的总长度
即不包括标记代码,但包括本字段
②哈夫曼表 数据长度-2字节
a)表ID和表类型 1字节 高4位:类型,只有两个值可选
0:DC直流;1:AC交流
低4位:哈夫曼表ID,
注意,DC表和AC表分开编码
b)不同位数的码字数量 16字节
c)编码内容 16个不同位数的码字数量之和(字节)
我们可以从 ①数据长度 得到哈夫曼表的总大小,这样可以保证不会读取出界。每个表的长度也可以从 b)不同位数的码字数量 得到,这16个字节的和就是这个表的长度。c)编码内容 并不是图像的数据内容,而是从小到大每个码字的权值,权值在建树时用不上,但是后面译码离不开它,因此在建树时也要保存每个码字的权值。
这里以一个哈夫曼表为例,介绍一下建立过程。
首先,第一个字节为表ID和表类型,这是以后译码需要的东西,保存下来,能和之后的树对应上即可。
其次,16个字节分别对应从1-16码长的编码个数,即第一个字节记录码长为1的编码个数,第二个为码长为2的编码个数,以此类推。。。因此这16个字节加起来即为所有编码个数,这也是很重要的。读取这16个字节的同时即可建立树,在建树的同时读取对应的权值保存即可,在读完的同时,树也建立完成~
对于读取到的编码个数,有两种情况,为0或者不为0(废话。。),下面讨论两种情况各自的处理办法:
为0
为0则说明没有该码长的编码,这就说明树生长到这里没有叶子,产生的均为内节点,则当前的每个节点都继续生长。
例如,读取的第一个字节为0,则说明码长为1的编码个数为0,这时就需要从根节点继续生长,即根节点产生左右儿子,并且这两个子节点均不是叶节点,再读取下一个字节的时候,这两个节点都需要继续生长。
不为0
不为0则说明该码长的编码有,假设为1,其他同理,依旧是第一个字节的时候,这时有一个根节点,并且其生长出来的一个儿子是叶节点,即该节点不会再生长,另一个儿子为内节点,读取下个字节的时候继续生长。
之后不断读取剩下的字节,根据上面进行处理,读完即可建立完树。
每个码字对应的权值在建树时即可读取,权值的位置可以由编码在16个字节中的位置和已读取的字节数推算出来,这个具体的关系画个图就可以看出来了。
PS:C/C++中的指针需要初始化,不然很容易内存泄露,后果都懂的,在找到毛病前,我的VS已经未响应了好多次。。。。
PPS:图像数据中可能会有多个DHT段,如果为了程序的兼容性,需要考虑到多个DHT段的情况,否则最终只记录了一个哈夫曼树的数据~
【原创】JPEG图像密写研究(二) 哈夫曼树的建立的更多相关文章
- 【原创】JPEG图像密写研究(三) 数据流译码
[原创]这次更新比较慢,译码过程比想象中复杂一些,更主要是译出来的DCT系数无法确定是否正确,要想验证就需要再进行正向压缩编码,再次形成jpeg图像验证正确,后续工作正在开展,这里就说一说译码的主要思 ...
- JPEG图像密写研究(一) JPEG图像文件结构
[转载]转载自http://www.cnblogs.com/leaven/archive/2010/04/06/1705846.html JPEG压缩编码算法的主要计算步骤如下: (0) 8*8分块. ...
- 哈夫曼树(二)之 C++详解
上一章介绍了哈夫曼树的基本概念,并通过C语言实现了哈夫曼树.本章是哈夫曼树的C++实现. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载 ...
- word2vec 中的数学原理二 预备知识 霍夫曼树
主要参考: word2vec 中的数学原理详解 自己动手写 word2vec 编码的话,根是不记录在编码中的 这一篇主要讲的就是霍夫曼树(最优二叉树)和编码. ...
- 树(二叉树 & 二叉搜索树 & 哈夫曼树 & 字典树)
树:n(n>=0)个节点的有限集.有且只有一个root,子树的个数没有限制但互不相交.结点拥有的子树个数就是该结点的度(Degree).度为0的是叶结点,除根结点和叶结点,其他的是内部结点.结点 ...
- Java数据结构(十二)—— 霍夫曼树及霍夫曼编码
霍夫曼树 基本介绍和创建 基本介绍 又称哈夫曼树,赫夫曼树 给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称为最优二叉树 霍夫曼树是带权路径长度最短的树,权值较 ...
- [原创.数据可视化系列之十二]使用 nodejs通过async await建立同步数据抓取
做数据分析和可视化工作,最重要的一点就是数据抓取工作,之前使用Java和python都做过简单的数据抓取,感觉用的很不顺手. 后来用nodejs发现非常不错,通过js就可以进行数据抓取工作,类似jqu ...
- HDU 3179 二叉搜索树(树的建立)
二叉搜索树 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 九度OJ 1107 搬水果 -- 哈夫曼树 2011年吉林大学计算机研究生机试真题
题目地址:http://ac.jobdu.com/problem.php?pid=1107 题目描述: 在一个果园里,小明已经将所有的水果打了下来,并按水果的不同种类分成了若干堆,小明决定把所有的水果 ...
随机推荐
- TCP应用编程--套接字C#实现
套接字之间的连接过程可以分为三个步骤: 1.服务器监听 2.客户端请求 3.连接确认 Ø服务器监听:是指服务器套接字并不定位具体的客户端套接字,而 是处于等待连接的状态,实时监控网络状态. Ø客户端 ...
- [Script]EBS里查看模块的版本、文件的版本信息【Z】
系统版本信息 装了哪些模块,以及版本信息 select 'Current Application Release: '||ver||' ('||bug||')' "Description&q ...
- C++, const:
问题: const成员函数和普通成员函数可以是同名同参数吗? 可以,这是一种函数的重载. const成员函数可不可以修改对象的成员变量的值? 不可以修改.//error C3490: ...
- c++常用IDE
vs2013. CodeLite (c/c++/PHP) codeBlocks Qt Creator Xcode
- [多线程同步练习]PV操作
看一个较为复杂的生产者-消费者问题: 问题描述 桌子上有一只盘子,每次只能向其中放入一个水果.爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等吃盘子中的橘子,女儿专等吃盘子中的苹果.只有盘子为空时 ...
- mysql 存储过程中的declare 和 set @的两种变量的区别
两者在手册中的说明: DECLARE var_name[,...] type [DEFAULT value]这个语句被用来声明局部变量.要给变量提供一个默认值,请包含一个DEFAULT子句.值可以被指 ...
- jQuery获取Select选择的Text和Value(详细汇总)
语法解释: 1. $("#select_id").change(function(){//code...}); //为Select添加事件,当选择其中一项时触发 2. var ch ...
- (6)Xamarin.android google map v2
原文 Xamarin.android google map v2 Google Map v1已经在2013年的3月开始停止支持了,目前若要在你的Android手机上使用到Google Map,就必须要 ...
- JAVA中的break[标签]continue[标签]用法
原文:JAVA中的break[标签]continue[标签]用法 注意:JAVA中的标签必须放在循环之前,且中间不能有其他语句.例如:tag:for或while或do--while; 1.使用brea ...
- 接口返回json
use Mojolicious::Lite; use JSON qw/encode_json decode_json/; # /foo?user=sri get '/api' => sub { ...