无损压缩的定义
所谓无损压缩格式,顾名思义,就是毫无损失地将声音信号进行压缩的音频格式。常见的像MP3、WMA等格式都是有损压缩格式,相比于作为源的WAV文件,它们都有相当大程度的信号丢失,这也是它们能达到10%的压缩率的根本原因。而无损压缩格式,就好比用Zip或RAR这样的压缩软件去压缩音频信号,得到的压缩格式还原成WAV文件,和作为源的WAV文件是一模一样的!但是如果用Zip或RAR来压缩WAV文件的话,必须将压缩包解压后才能播放。而无损压缩格式则能直接通过播放软件实现实时播放,使用起来和MP3等有损格式一模一样。总而言之,无损压缩格式就是能在不牺牲任何音频信号的前提下,减少WAV文件体积的格式。
经常使用的无损压缩算法有 Shannon-Fano 编码,Huffman 编码,行程(Run-length)编码,LZW(Lempel-Ziv-Welch)编码和算术编码等。
Huffman 编码
该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码。它是统计独立信源能达到最小平均码长的编码方法。编码效率高 。
基本原理:
依据信源字符出现的概率大小来构造代码,对出现概率较大的信源字符,给予较短码长,而对于出现概率较小的信源字符,给予较长的码长,最后使得编码的平均码字最短。
编码步骤:
(1)初始化,根据符号概率的大小按由大到小顺序对符号进行排序。
(2)把概率最小的两个符号组成一个节点。
(3)重复步骤2。
(4)从根节点开始到相应于每个符号的“树叶”,从上到下标上“0”(上枝)或者“1”(下枝)至于哪个为“1”哪个为“0”则无关紧要,最后的结果仅仅是分配的代码不同,而代码的平均长度是相同的。
(5)从根节点开始顺着树枝到每个叶子分别写出每个符号的代码。
Huffman编码的注意点:
Huffman编码没有错误保护功能,如果码中有错误,则可能引起接下来的一连串译码错误。
Huffman编码是可变长编码,因此很难随意查找或调用中的文件内容。
Huffman依赖于信源的统计特性。 Huffman编码的每个码字都是整数:因此实际上平均码长很难达到信息熵的大小。
Huffman编码解码必须要有码表,如果消息数目很多,那么所需要存储的码表也很大,这将影响系统的存储量及编、译码速度。
算数编码
算术编码把一个信源集合表示为实数线上的0到1之间的一个区间。这个集合中的每个元素都要用来缩短这个区间。信源集合的元素越多,所得到的区间就越小,当区间变小时,就需要一些更多的数位来表示这个区间,这就是区间作为代码的原理。算术编码首先假设一个信源的概率模型,然后用这些概率来缩小表示信源集的区间。
算术编码用到两个基本的参数:
符号的概率和它的编码间隔
信源符号的概率决定压缩编码的效率,也决定编码过程中信源符号的间隔,而这些间隔包含在0到1之间 。
在算术编码中需要注意的几个问题:
1、由于实际的计算机的精度不可能无限长,运算中出现溢出是一个明显的问题,但多数机器都有16位、32位或者64位的精度,因此这个问题可使用比例缩放方法解决。
2、算术编码器对整个消息只产生一个码字,这个码字是在间隔[0,1)中的一个实数,因此译码器在接受到表示这个实数的所有位之前不能进行译码。
3、算术编码也是一种对错误很敏感的编码方法,如果有一位发生错误就会导致整个消息译错。
行程(Run-length)编码
RLE( Run - Length Encoding)是一个针对包含有顺序排列的多次重复的数据的压缩方案。其原理就是把一系列的重复值用一个单独的值再加上一个计数值来取代,行程长度就是连续且重复的单元数目。如果想得到原始数据,只需展开这个编码就可以了。
对比RLE编码前后的代码数可以发现,在编码前要用73个代码表示这一行的数据,而编码后只要用10个代码表示代表原来的73个代码,压缩前后的数据量之比约为771,即压缩比为7:1。这说明RLE确实是一种压缩技术,而且编码技术实用。
RLE的性能好坏主要取决于图像本身的特点。RLE压缩编码尤其适用于计算机生成的图像,对减少图像文件的存储空间非常有效。然而,由于颜色丰富的自然图像在同一行上具有相同颜色的连续像素往往很少,而连续几行都具有相同颜色值的连续行数就更少,如果仍然使用RLE编码方法,不仅不能压缩图像数据,反而可能使原来的图像数据变得更大 。
译码时按照与编码时采用的相同规则进行,还原后得到的数据与压缩前的数据完全相同。
因此,RLE属于无损压缩技术它被用于BMP、JPEG/MPEG、TIFF和PDF等编码之中,还被用于传真机。
LZW编码
LZW通过建立一个字符串表,用较短的代码来表示较长的字符串来实现压缩。字符串和编码的对应关系是在压缩过程中动态生成的,并且隐含在压缩数据中,解压的时候根据表来进行恢复,是一种无损压缩,全称 Lempel-ziy- Welch encoding,简称LZW的压缩算法 。
基本原理
提取原始文本文件数据中的不同字符,基于这些字符创建一个编译表,然后用编译表中的字符的索引来替代原始文本文件数据中的相应字符,减少原始数据大小。看起来和调色板图象的实现原理差不多,但是应该注意到的是,我们这里的编译表不是事先创建好的,而是根据原始文件数据动态创建的,解码时还要从已编码的数据中还原出原来的编译表 。
LZW编码算法的具体执行步骤如下步骤:
1、开始时的词典包含所有可能的根(Root),而当前前缀P是空的;
2、当前字符(C):=字符流中的下一个字符;
3、判断级-符串P+C是否在词典中
(1)如果“是”:P:=P+C//(用C扩展P)
(2)如果“否
①把代表当前前缀P的码字输出到码字流
②把缀-符串P+C添加到词典;
③令P:=C/(现在的P仅包含一个子符C)
4、判断码字流中是否还有码字要译
(1)如果“是”,就返回到步骤2
(2)如如果“否”
①把代表当前前缀P的码输出到码字流
②结束