Huffman 编码压缩

引,工作了,大学里学的忘记的差不多了。
    碰巧在工作中做一些东西的时候,遇到了自己大学时代想要完成却因为学业,以及各种娱乐而没能完成的事情。所以就想趁着空闲,把这些事情完成。
    还记得上大二的时候,教数据结构的老师给我们将了一个Huffman的编码算法,总感觉抓到了一些东西,想用它做点东西出来,但是却因为没什么时间去上网查查资料,所以导致了考试考的很好,考过之后忘记了,不知道怎么用这个编码去做出点实际的东西。只是听说可以用来做压缩。现在唯一记得就是 贪心的思想。
------------------------------------------------------------
正题,现在,准备研究一下压缩的实现,所以回忆起用Huffman来做字节上的压缩。这里压缩的思想就不赘述了。碰到的问题有:
    1. 原文件每个字节对应的 Huffman 编码要做成一个“表”或者类似于表的东西,放进压缩文件里。这个表是用来解压缩的,原先我的设计是把表做成形如:“AS0001EBS1000E”A 表示源文件中的字节,S标志编码的开始,E表示编码的结束。所以源文件中的A可以表示成二进制 0001.B表示成二进制 1000. 但是解析起来比较麻烦,并且表的空间看上去有点大,问,大家有木有比较好的格式。

    2. 1中的表,因为和压缩好的内容是放一个文件中的,那么如何在解压缩的时候分离出这个表?我的想法是在文件开始位置加个值,做成形如: "HUF"+SIZE+"E"+"AS0001EBS1000E"+"压缩内容"。 同样感觉解析比较麻烦。

----------------------------

续1,对于问题1,自己没有好好想一些更好的方案,在网上看压缩相关的资料时候,看到原来别人都是存储字符频率的,可以用这个重构Huffman树。这样空间上1个字节存储字符,4个字节存储频率。比自己想到的方案要好N倍。我好搓啊....

         对于问题2,还是保持原状。改不动它。

----------------------------

续2,Huffman编码压缩已经完成,但是压缩率很低,对于压缩过的文件压缩反而会增大。试着写一个LZ77或者LZW的算法增加压缩率。

        看了很多最终还是选中LZ77的算法,比较泛用一些,每个字节增加一个标志位,相同字符串用大小为两个字节的相对偏移量表示。

        窗口大小暂时选定为32个字节,先写好流程,剩下的慢慢优化。

---------------------------

续3,LZ77算法,没有去看原始的论文,学习了大致的思路,按照自己的想法写了一下。

        主要就是一个是匹配,一个是窗口的移动,还有就是字节的映射。

        基本算法已经实现,对于图片压缩之后反而压缩之后变得更大。没有优化和改进的算法果然还是比不上一些当下流行的压缩代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以帮你解决这个问题。 首先,Huffman编码是一种基于频率的编码方法,可以将出现频率较高的字符或符号用较短的编码表示,出现频率较低的字符或符号用较长的编码表示,从而减小数据的存储空间。 针对一张图像的Huffman编码压缩,我们需要先读取该图像的二进制数据,然后统计每个像素值出现的频率,根据频率构建Huffman树,生成每个像素值的编码,将像素值替换为对应的编码,并将编码输出到文件中。 下面是一个简单的Python实现: ```python import heapq import os class HuffmanCoding: def __init__(self, path): self.path = path self.heap = [] self.codes = {} self.reverse_mapping = {} # 统计每个像素值出现的频率 def make_frequency_dict(self, data): frequency = {} for pixel in data: if pixel not in frequency: frequency[pixel] = 0 frequency[pixel] += 1 return frequency # 构建Huffman树 def build_huffman_tree(self, frequency): for pixel in frequency: node = HuffmanNode(pixel, frequency[pixel]) heapq.heappush(self.heap, node) while len(self.heap) > 1: node1 = heapq.heappop(self.heap) node2 = heapq.heappop(self.heap) merged = HuffmanNode(None, node1.frequency + node2.frequency) merged.left = node1 merged.right = node2 heapq.heappush(self.heap, merged) # 生成每个像素值的编码 def make_codes_helper(self, root, current_code): if root is None: return if root.pixel is not None: self.codes[root.pixel] = current_code self.reverse_mapping[current_code] = root.pixel return self.make_codes_helper(root.left, current_code + "0") self.make_codes_helper(root.right, current_code + "1") def make_codes(self): root = heapq.heappop(self.heap) current_code = "" self.make_codes_helper(root, current_code) # 将像素值替换为对应的编码,并将编码输出到文件中 def get_encoded_data(self, data): encoded_data = "" for pixel in data: encoded_data += self.codes[pixel] padded_length = 8 - len(encoded_data) % 8 for i in range(padded_length): encoded_data += "0" padded_info = "{0:08b}".format(padded_length) encoded_data = padded_info + encoded_data b = bytearray() for i in range(0, len(encoded_data), 8): byte = encoded_data[i:i+8] b.append(int(byte, 2)) return bytes(b) # 将编码输出到文件中 def compress(self): filename, file_extension = os.path.splitext(self.path) output_path = filename + ".bin" with open(self.path, 'rb') as file, open(output_path, 'wb') as output: data = file.read() frequency = self.make_frequency_dict(data) self.build_huffman_tree(frequency) self.make_codes() encoded_data = self.get_encoded_data(data) output.write(encoded_data) print("Compressed file saved as", output_path) class HuffmanNode: def __init__(self, pixel, frequency): self.pixel = pixel self.frequency = frequency self.left = None self.right = None self.code = "" if __name__ == '__main__': path = "/path/to/image.jpg" h = HuffmanCoding(path) h.compress() ``` 这段代码可以对指定的图像进行Huffman编码压缩,并将压缩后的数据输出到一个新文件中。你只需要将代码中的 `path` 变量修改为你要压缩的图像的路径即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值