huffman 编码示例程序

本人开发环境为VS2013。

如图1所示:本程序是对0-255这256个符号进行编码


图1. HUFF_ENC.C程序中的注释部分


图2. 命令参数说明

因此,我选择了一幅yuv格式图像进行编码,为了方便观察编码后的码字,输出文件选择了huff格式,程序参数可在 项目--> 属性 --> 配置属性 --> 调试 --> 命令参数中输入:

-i test_512x256_420.yuv输入文件名)  -o output.huff输出文件名)

注意:-i和-o不能省略,否则在调试到getopt函数的时候,程序会认为没有输入文件名,即 t=0(t 是输入文件名是否已经给出的标志位),这时程序会创建一个临时文件,如图3:


图3. 创建临时输入文件

同时文件名中不能包含空格,否则在将文件名字符串赋值给程序中参数的时候会发生错误。

利用fseek函数将输入文件的文件指针指向文件尾:fseek(ifp, 0, SEEK_END),再利用ftell函数得到输入文件的文件指针当前位置(文件尾)相对于文件首的偏移字节数,即输入文件的大小(输入文件分辨率为512*256,色度取样格式为4:2:0,所以文件大小为512*256*1.5=196608)如图4:


图4:文件大小

++size 的作用是:

value(values, file, size, num); 函数用来计算输入文件中0-255每个像素值出现的次数,prob[256] 数组用来存储256个像素值分别出现的频率(概率),sort(prob, loc, num); 函数用来将概率从大到小排序:首先将svalue中256个元素全部置为0,再找出256个元素中概率为0的像素值,然后倒序(从第256个元素开始)存储在svalue中,再寻找元素中概率最大的像素值,用maxloc来记录概率最大的像素值,再将该像素值正序(从第1个元素开始)赋值给svalue,loc按正序记录着拥有最大概率的像素值,,然后将value中最大的概率置为0,在进行下一轮的比大小,最终loc数组中储存着概率从大到小排列的像素值,svalue中储存着从大到小排列的概率,再将svalue中数值按顺序赋值给value数组。

huff(prob,loc,num, code, length); 函数:create_list 函数有三个参数:概率,位置,码元总数,我对create_list 函数的理解是,首先用节点head、tail 以及中间节点 b 产生了一条概率由大到小排列的链,概率链结束后tail节点代表概率最小的像素值节点,将其作为其父节点的右节点,tail->back作为其父节点的左节点,(这也是概率最小的两个节点)然后解开原始的概率链,父节点的概率等于左右节点的概率之和,再将父节点的概率加进概率链,以此类推,创建一棵二叉树,最终的父节点是二叉树的开始(头结点),编码即为0。create_code 函数用来检查当它被调用时给定的节点是否是“树叶”:如果是,这个节点的代码和长度被分别写入相应的数组;如果不是,树中的下一个节点的代码将被写入,左节点分配0,右节点分配1。

之后是对源文件进行压缩编码,首先为压缩文件分配内存空间: compressed_file = (unsigned char*) malloc (size * 2 * sizeof(unsigned char) ); 乘以2的意义是:分配足够的内存空间。files(size, code, length, file, compressed_file); 函数:对输入文件进行编码,如图5:


图5. file函数中的一段程序

其中,v 代表图像中的第 i 个像素的取值,w 是一个由一个1和若干个0组成的二进制数,1在首位,0的个数取决于该像素取值的码字,1和0的总位数等于码字的位数,c 代表该像素值的码字,换算成十进制,word 是一个unsigned char型的变量,8bit,l 用来计比特数,每到8(即一字节),就将word 中的二进制数写入压缩文件compressed_file 中,count用来记录字节数,每写入一字节,count 加1 ,word 以及 l 清空,进行下一次的存储。如果对输入文件中所有像素编码结束后 l 的值不为0,即 word 中至少有2bit ( word<<=1;)的码字,所以将word 中的剩余 bit 补足一字节写入压缩文件。最后返回count 值(即压缩文件中有多少字节数)。如图6:

 

图6. 调试中间结果截图

最终,写输出文件:先将256个像素值的码字写入输出文件,再将256个码字其各自长度写入输出文件(如果命令参数中有storecod文件,则将码字与长度写入storecod文件,因为我没有设置该文件,所以写入输出文件中),最后将整幅图片的压缩编码数据写入输出文件。如图7:


图7. 输出文件大小

输出文件大小:4(每个码字 unsigned int 型:4字节)*256+1(记录码字长度 char 型:1字节)*256+185426=186706字节

输入文件大小192KB,原图如图8:


图8. 输入文件test_512x256_420.yuv

huffman编码后的结果如下:


图9. 编码结果(码字)


图10. 编码结果(码字长度)


图11. 编码结果(图像的压缩编码)

用VS查看编码结果,前64行的结果是256个码字,接下来16行的结果是256个码字的长度,剩下的数据则是图像的编码数据。

下面看三幅png格式的图片:

                      

                                        (a) earth                                                     (b) omaha                                                   (c) sensin

图12. 三幅示例图片

三幅图片的原文件大小分别为26995 Bytes、50185 Bytes 以及 34488 Bytes,压缩编码后的文件大小分别为28257 Bytes、51449 Bytes 以及 35734 Bytes,可以看出压缩后的文件反而比原文件还要大。在对统计信息有大幅变化的信源进行编码时,在给出信源压缩表示的同时,还需要给出 huffman 码,当符号集很大时,这可能会成为严重负担,甚至可能抵消压缩带来的所有好处。

以上,用实例分析了huffman编码的具体步骤,并大致分析了实验结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Huffman编码是一种无损数据压缩算法,通过将出现频率较高的字符使用较短的编码,出现频率较低的字符使用较长的编码,来达到压缩数据的目的。下面是一个简单的Huffman编码程序实现: ```python import heapq from collections import defaultdict class Node: def __init__(self, freq, char=None): self.freq = freq self.char = char self.left = None self.right = None def __lt__(self, other): return self.freq < other.freq def huffman_encode(text): # 统计字符出现的频率 freq = defaultdict(int) for char in text: freq[char] += 1 # 构建Huffman树 heap = [Node(f, c) for c, f in freq.items()] heapq.heapify(heap) while len(heap) > 1: left = heapq.heappop(heap) right = heapq.heappop(heap) parent = Node(left.freq + right.freq) parent.left = left parent.right = right heapq.heappush(heap, parent) root = heap[0] # 生成Huffman编码表 codes = {} def generate_codes(node, code): if node.char: codes[node.char] = code if node.left: generate_codes(node.left, code + '0') if node.right: generate_codes(node.right, code + '1') generate_codes(root, '') # 编码文本 encoded_text = ''.join(codes[char] for char in text) return encoded_text, codes ``` 使用示例: ```python text = "hello world" encoded_text, codes = huffman_encode(text) print("Encoded text:", encoded_text) print("Huffman codes:") for char, code in codes.items(): print(f"{char}: {code}") ``` 输出: ``` Encoded text: 1010011011011110010100110001101111101 Huffman codes: h: 110 e: 00 l: 11 o: 101 w: 1001 r: 1000 d: 010 ``` 可以看到,字符出现频率较高的字符(h、e、l、o)使用的编码较短,出现频率较低的字符(w、r、d)使用的编码较长,从而实现了文本的压缩。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值