arm11中的JPEG 编解码器

霍夫曼编码是一种被广泛应用而且非常有效的数据压缩技术,根据待压缩数据的特征,一个可压缩掉20%~90%。这里考虑的数据指的是字符串序列。要理解霍夫曼编码,先要理解霍夫曼树,即最优二叉树,是一类带权路径长度最短的树。

路径是指从树中一个结点到另一个结点之间的通路,路径上的分支数目称为路径长度。

树的路径长度是从树根到每一个叶子之间的路径长度之和。结点的带权路径长度为从该结点到树根之间的路径长度与该结点权的乘积,树的带权路径长度为树中所有叶子结点的带权路径长度之和.

霍夫曼树是指所有叶子结点的二叉树中带权路径长度最小的二叉树.

当给定了n个叶子结点的权值后,构造出的最优二叉树的结点数目m就确定了,即m=2n-1,所以可用一维结构树组来存储最优二叉树

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#define MAXLEAFNUM 50 /*最优二叉树中最大叶子树目*/
  
struct node{
  
char ch; /*当前结点表示的字符,对于非叶子结点,此域不用*/
  
int weight; /*当前结点的权值*/
  
int parent; /*当前结点的父结点的下标,为0时表示无父结点*/
  
int lchild,rchild; /*当前结点的左,右孩子结点的下标,为0时表示无孩子结点*/
  
}HuffmanTree[2 * MAXLEAFNUM];
  
typedef char *HuffmanCode[MAXLEAFNUM + 1];
  
创建最优二叉树
  
void createHTree(HuffmanTree HT, char *c, int *w, int n)
  
{
  
/*数组c[0..n-1]和w[0..n-1]存放了n个字符及其概率,构造霍夫树HT*/
  
int i, s1, s2;
  
if (n <= 1)
  
return ;
  
/*根据n个权值构造n棵只有根结点的二叉树*/
  
for (i=1; i<=n; i++)
  
{
  
HT[i].ch = c[i-1];
  
HT[i].weight = w[i-1];
  
HT[i].parent = HT[i].lchild = HT[i].rchild = 0;
  
}
  
for (; i<2*n; ++i)
  
{
  
HT[i].parent = 0;
  
HT[i].lchild = 0;
  
HT[i].rchild = 0;
  
}
  
/*构造霍夫曼树*/
  
for (i=n+1; i<2*n; i++)
  
{
  
/*从HT[1..i-1]中选择parent为0且weight最小的两棵树,其序号为s1和s2*/
  
select(HT,i-1,s1,s2);
  
HT[s1].parent = i;
  
HT[s2].parent = i;
  
HT[i].lchild = s1;
  
HT[i].rchild = s2;
  
HT[i].weight = HT[s1].weight + HT[s2].weight;
  
}
  
}

应用霍夫曼编码

假设有一个包含100 000个字符的数据文件要压缩存储。各字符在该文件中的出现频度见表1。仅有6种不同字符出现过,字符a出现了45000次。

                   a     b     c     d      e      f
频度(千字)      45    13    12    16     9      5固定代码字      000    001   010    011   100   101变长代码字      0      101   100    111   1101  1100

表1  一个字符编码问题。大小为100 000个字符的一个数据文件仅包含字符a~f,每个字符出现的频度如表中所示。如果对每个字符赋予一个三位的编码,则该文件可被编码为300000位。如果利用表中的可变长度编码,该文件可被编码为224000位。

可以用很多种方式来表示这样一个文件。采用固定长度编码,则需要三位二进制数字来表示六个字符:a=000,b=001,…,f=101。这种方法需要300 000来对整个原文件编码。

而可变长度编码是对频度高的字符赋以短编码,而对频度低的字符赋以较长一些的编码。表1显示了这种编码,其中一位串0表示a,四位串1100表示f。这种编码方式需要(45*1+13*3+12*3+16*3+9*4+5*4)*1000 = 224 000 位来表示整个文件,即可压缩掉约25%。这其实就是最优字符编码(霍夫曼编码)

前缀编码

我们这里考虑的编码方案中,没有一个编码是另一个编码的前缀。这样的编码称为前缀编码(或许“无前缀编码“是个更好的名字,但是前缀编码是标准的书面语)。

对任何一种二进制字符编码来说编码总是简单的,这只要将文件中表示每个字符的编码并置起来即可。利用表1的可变长度编码,把包含三个字符的文件abc编成

0 . 101 . 100 = 0 101 100,其中“.“表示并置。

在前缀编码中解码也是很方便的。因为没有一个码是其他码的前缀,故被编码文件的开始处的编码是确定的。我们只要识别出第一个编码,将它翻译成原文字符,再对余下的编码文件重复这个解码过程即可。在我们的例子中,可将串001 011 101唯一地分析为0.0.101.1101,因此可解码为aabe。

解码过程需要有一种关于前缀编码的方便表示,使得初始编码可以很容易地被识别出来。有一种表示方法就是叶子为给定字符的二叉树。在这种树中,我们将一个字符的编码解释为从根至该字符的路径,其中0表示“转向左子结点”,1表示“转向右子结点“。如下给出最优二叉树,如图1。

以下给出查找最优二叉树叶子结点编码的算法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
typedef char *HuffmanCode[MAXLEAFNUM + 1];(本文开头也有说明)
  
void HuffmanCoding(HuffmanTree HT, HuffmanCode HC, int n)
  
{
  
/* n个叶子结点在霍夫曼树HT中的下标为1~n,*/
  
  /*第i(1<= i <= n)个叶子的编码存放HC[i]中*/
  
char *cd;
  
  int i,start,c,f;
  
  if (n<=1) 
  
return ;
  
  /*分配n个字节的内存,用来存放当前得到的编码*/
  
  /*n个叶子结点最大的编码长度为n所以分配n个字节*/
  
cd = ( char *) malloc (n)
  
  cd[n-1] = ‘\0’;
  
for (i=1; i<=n; i++)
  
{
  
start = n -1;
  
for (c=i,f=HT[i].parent; f!=0; c=f,f=HT[f].parent)
  
/*从叶子结点开始查找编码*/
  
/*叶子结点的父结点的左子树为叶子结点,则编码为0*/
  
/*否则就为父结点的右子树,则编码为1*/
  
if (HT[f].lchild = = c) cd[--start] = ‘0’;
  
else cd[--start] = ‘1’;
  
    /*分配内存,分配内存的字节数为当前得到的字符编码数*/
  
    HC[i] = ( char *) malloc (n-start);
  
    strcpy (HC[i], &cd[start]);
  
}
  
free (cd);
  
}

译码算法为:

从根结点出发,按二进制位串中的0和1确定是进入左分支还是右分支,当到达叶子结点时译出该叶子对应的字符。数据文件(包含编码)未结束,则回到根结点继续进行上述过程。

给出如下函数:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void Decoding(HuffmanTree HT, int n, char *buff)
  
{
  
/*利用具有n个叶子结点的最优二叉树(存储在数组HT中)进行译码,叶子的下标*/
  
/*为1~n,buff指向数据文件的编码序列*/
  
int p = 2*n -1; /*指向根结点*/
  
while (*buff)
  
{
  
if ((*buff) = = ‘0’) p = HT[p].lchild; /*进入左分支*/
  
else p = HT[p].rchild; /*进入右分支*/
  
/*到达一个叶子结点*/
  
if (HT[p].lchild = = 0 && HT[p].rchild = = 0)
  
{
  
printf (“%c”, HT[p].ch);
  
p = 2*n – 1; /*回到根结点*/
  
}
  
buff++;
  
}
  
}

http://download.csdn.net/detail/jnwangcan/4506459  (arm学习资料大全700M)

JPEG 编解码器 霍夫曼编码相关推荐

  1. JPEG编码过程中的霍夫曼编码

    JPEG编码过程中的霍夫曼编码 jpeg文件中的霍夫曼编码分两个部分对DC系数编码和对AC系数的编码. DC系数的编码 编码过程 DC系数的编码由两部分组成, huffman 编码的bitlen + ...

  2. JPEG霍夫曼编码教程

    转译自:https://www.impulseadventure.com/photo/jpeg-huffman-coding.html 量化后,霍夫曼/熵编码是JPEG压缩文件大小节省的重要因素之一. ...

  3. 灵光一现的创造——霍夫曼编码

    点击上方"LiveVideoStack"关注我们 作者 | Alex 技术审校 | 赵军 霍夫曼 声影传奇 #004# 作为一名科学家和老师,我真的非常执着.如果我觉得自己还没有找 ...

  4. 霍夫曼算法_霍夫曼编码算法

    霍夫曼算法 In this tutorial, we'll be discussing and implementing the Huffman Coding Algorithm in Java. 在 ...

  5. 图像处理—霍夫曼编码

    图像压缩编码是专门研究图像数据压缩的技术,就是尽量减少表示数据图像所需要的数据量. 本章主要介绍图像压缩编码的基础知识,重点讲解常用的图像压缩编码方法,如霍夫曼编码.香农编码.算术编码.行程编码和预测 ...

  6. 可逼近信道容量编码技术之霍夫曼编码的实现

    可逼近信道容量编码技术之霍夫曼编码的实现 简介 在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视.哈夫曼编码正是一种应用广泛且非常有效 ...

  7. 【数据结构】图解霍夫曼编码,看了就能懂

    今天来给大家普及一下霍夫曼编码(Huffman Coding),一种用于无损数据压缩的熵编码算法,由美国计算机科学家大卫·霍夫曼在 1952 年提出--这么专业的解释,不用问,来自维基百科了. 说实话 ...

  8. 信息论4—无失真信源编码(非延长码,霍夫曼编码)

    无失真信源编码 单义可译码 码字非奇异,码字序列非奇异. 单义可译定理--克拉夫不等式 非延长码(即时码,在无失真信源编码中,常采用此码) 延长码:部分码字是其它码字的前缀.100是10的延长码,01 ...

  9. 数据结构与算法 / 霍夫曼树、霍夫曼编码和解码

    一. 诞生原因 找出存放一串字符所需的最少的二进制编码. 二. 构造方法 首先统计出每种字符出现的频率,即:概率.权值. 例如:频率表 A:60,    B:45,   C:13   D:69   E ...

最新文章

  1. 30 天精通 RxJS (05): 建立 Observable(一)
  2. Deap : 遗传算法算法解决 背包问题
  3. 如何在 Linux 虚拟机上扩展根文件系统
  4. 当开启了延迟加载的开关,对象是怎么变成代理对象的?
  5. SQLite的基本使用一
  6. RabbitMQ简介和六种工作模式详解
  7. [html] 常见的浏览器内核都有哪些?并介绍下你对内核的理解
  8. JavaBean为什么要实现Serializable接口
  9. SAP License:销售流程
  10. 我的2009:知识管理篇
  11. Atitti css transition Animation differ区别
  12. Day771.Redis好用的运维工具 -Redis 核心技术与实战
  13. 0.3-87 GHz频段手持频谱分析仪 —— SAF Spectrum Compact
  14. python 视频转图片
  15. Windows Mobile Pocket PC的文件系统
  16. ArcGIS 教程:Workflow Manager 快速浏览
  17. wannier拟合能带总是拟合不上_科学网—Wannier90输入文件中num_wann, num_bands, 和energy window等参数设置规则 - 李云海的博文...
  18. linux命令返回结果保存到文件,Linux终端运行命令及结果同时保存入文件方法总结...
  19. @Transactional失效情况
  20. HDU 1846-Brave Game(巴什博弈-SG函数)

热门文章

  1. dm800串口刷机方法_2020年获得800免费电话号码的7种方法
  2. https中文乱码问题
  3. 部署完zabbix服务后,修改defines.inc.php后,中文依旧乱码问题
  4. oracle 消耗资源的语句,Oracle高资源消耗SQL语句定位
  5. 智能商贸-day11-采购报表功能
  6. Qt实现一个隐式共享类(使用QSharedDataPointer)
  7. 梦幻服务器系统维护后多久再登录,梦幻西游:系统维护后出现重大漏洞,官方发文紧急停机修复?...
  8. MySQL计算时间差函数
  9. 改变你的文字 改变你的世界
  10. Maven编译Scala报错StackOverflowError