C#哈夫曼编码压缩图片

时间: 2023-07-12 21:03:55 浏览: 60
实现哈夫曼编码压缩图片的基本步骤如下: 1. 读入图片文件,将每个像素点的颜色值转化成二进制字符串。 2. 统计每个二进制字符串的出现次数,建立哈夫曼树。 3. 根据哈夫曼编码表,将每个二进制字符串进行编码。 4. 将编码后的二进制字符串写入文件,同时将哈夫曼编码表也写入文件。 5. 读入压缩文件和哈夫曼编码表,解码成原始的二进制字符串。 6. 将解码后的二进制字符串转化成像素点的颜色值。 7. 将像素点的颜色值写入文件,生成解压后的图片。 这里提供一个C#的哈夫曼编码压缩图片的例子,代码如下: ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace HuffmanCompression { class Program { static void Main(string[] args) { string inputFilePath = "input.bmp"; string outputCompressedFilePath = "output.bin"; string outputDecompressedFilePath = "output.bmp"; // 读入图片文件,将每个像素点的颜色值转化成二进制字符串 byte[] inputBytes = File.ReadAllBytes(inputFilePath); string inputBinaryString = ""; for (int i = 54; i < inputBytes.Length; i += 3) { byte r = inputBytes[i + 2]; byte g = inputBytes[i + 1]; byte b = inputBytes[i]; string binaryString = Convert.ToString(r, 2).PadLeft(8, '0'); binaryString += Convert.ToString(g, 2).PadLeft(8, '0'); binaryString += Convert.ToString(b, 2).PadLeft(8, '0'); inputBinaryString += binaryString; } // 统计每个二进制字符串的出现次数,建立哈夫曼树 Dictionary<string, int> frequencies = new Dictionary<string, int>(); for (int i = 0; i < inputBinaryString.Length; i += 8) { string subString = inputBinaryString.Substring(i, 8); if (frequencies.ContainsKey(subString)) { frequencies[subString]++; } else { frequencies.Add(subString, 1); } } HuffmanTree huffmanTree = new HuffmanTree(frequencies); // 根据哈夫曼编码表,将每个二进制字符串进行编码 Dictionary<string, string> encodingTable = huffmanTree.GetEncodingTable(); string outputBinaryString = ""; for (int i = 0; i < inputBinaryString.Length; i += 8) { string subString = inputBinaryString.Substring(i, 8); outputBinaryString += encodingTable[subString]; } // 将编码后的二进制字符串写入文件,同时将哈夫曼编码表也写入文件 byte[] outputBytes = new byte[outputBinaryString.Length / 8 + 1]; int byteIndex = 0; int bitIndex = 0; foreach (char bit in outputBinaryString) { if (bit == '1') { outputBytes[byteIndex] |= (byte)(1 << (7 - bitIndex)); } bitIndex++; if (bitIndex == 8) { byteIndex++; bitIndex = 0; } } File.WriteAllBytes(outputCompressedFilePath, outputBytes); using (StreamWriter writer = new StreamWriter(outputCompressedFilePath + ".table")) { foreach (string key in encodingTable.Keys) { writer.WriteLine(key + " " + encodingTable[key]); } } // 读入压缩文件和哈夫曼编码表,解码成原始的二进制字符串 byte[] compressedBytes = File.ReadAllBytes(outputCompressedFilePath); string compressedBinaryString = ""; foreach (byte compressedByte in compressedBytes) { for (int i = 0; i < 8; i++) { if ((compressedByte & (1 << (7 - i))) != 0) { compressedBinaryString += "1"; } else { compressedBinaryString += "0"; } } } Dictionary<string, string> decodingTable = new Dictionary<string, string>(); using (StreamReader reader = new StreamReader(outputCompressedFilePath + ".table")) { string line; while ((line = reader.ReadLine()) != null) { string[] parts = line.Split(' '); decodingTable.Add(parts[1], parts[0]); } } string decompressedBinaryString = ""; string currentBinaryString = ""; foreach (char bit in compressedBinaryString) { currentBinaryString += bit; if (decodingTable.ContainsKey(currentBinaryString)) { decompressedBinaryString += decodingTable[currentBinaryString]; currentBinaryString = ""; } } // 将解码后的二进制字符串转化成像素点的颜色值 byte[] decompressedBytes = new byte[decompressedBinaryString.Length / 8 * 3 + 54]; Array.Copy(inputBytes, 0, decompressedBytes, 0, 54); for (int i = 0; i < decompressedBinaryString.Length; i += 24) { string subString = decompressedBinaryString.Substring(i, 24); byte r = Convert.ToByte(subString.Substring(0, 8), 2); byte g = Convert.ToByte(subString.Substring(8, 8), 2); byte b = Convert.ToByte(subString.Substring(16, 8), 2); decompressedBytes[i / 8 * 3 + 54] = b; decompressedBytes[i / 8 * 3 + 55] = g; decompressedBytes[i / 8 * 3 + 56] = r; } // 将像素点的颜色值写入文件,生成解压后的图片 File.WriteAllBytes(outputDecompressedFilePath, decompressedBytes); } } class HuffmanTree { private Node root; public HuffmanTree(Dictionary<string, int> frequencies) { PriorityQueue<Node> priorityQueue = new PriorityQueue<Node>(); foreach (string key in frequencies.Keys) { priorityQueue.Enqueue(new Node(key, frequencies[key])); } while (priorityQueue.Count > 1) { Node left = priorityQueue.Dequeue(); Node right = priorityQueue.Dequeue(); priorityQueue.Enqueue(new Node(left, right)); } root = priorityQueue.Dequeue(); } public Dictionary<string, string> GetEncodingTable() { Dictionary<string, string> encodingTable = new Dictionary<string, string>(); Traverse(root, "", encodingTable); return encodingTable; } private void Traverse(Node node, string prefix, Dictionary<string, string> encodingTable) { if (node.IsLeaf()) { encodingTable.Add(node.Value, prefix); } else { Traverse(node.Left, prefix + "0", encodingTable); Traverse(node.Right, prefix + "1", encodingTable); } } private class Node : IComparable<Node> { public string Value { get; set; } public int Frequency { get; set; } public Node Left { get; set; } public Node Right { get; set; } public Node(string value, int frequency) { Value = value; Frequency = frequency; } public Node(Node left, Node right) { Left = left; Right = right; Frequency = left.Frequency + right.Frequency; } public bool IsLeaf() { return Left == null && Right == null; } public int CompareTo(Node other) { return Frequency - other.Frequency; } } } class PriorityQueue<T> where T : IComparable<T> { private List<T> elements; public PriorityQueue() { elements = new List<T>(); } public void Enqueue(T element) { elements.Add(element); int index = elements.Count - 1; while (index > 0) { int parentIndex = (index - 1) / 2; if (elements[parentIndex].CompareTo(elements[index]) <= 0) { break; } T temp = elements[parentIndex]; elements[parentIndex] = elements[index]; elements[index] = temp; index = parentIndex; } } public T Dequeue() { T result = elements[0]; elements[0] = elements[elements.Count - 1]; elements.RemoveAt(elements.Count - 1); int index = 0; while (true) { int leftChildIndex = index * 2 + 1; int rightChildIndex = index * 2 + 2; if (leftChildIndex >= elements.Count) { break; } int smallerChildIndex = leftChildIndex; if (rightChildIndex < elements.Count && elements[rightChildIndex].CompareTo(elements[leftChildIndex]) < 0) { smallerChildIndex = rightChildIndex; } if (elements[index].CompareTo(elements[smallerChildIndex]) <= 0) { break; } T temp = elements[index]; elements[index] = elements[smallerChildIndex]; elements[smallerChildIndex] = temp; index = smallerChildIndex; } return result; } public int Count { get { return elements.Count; } } } } ``` 注意:这个例子只是实现了对 BMP 格式的图片进行哈夫曼编码压缩和解压,如果要处理其他格式的图片,需要根据具体的格式进行解析。

相关推荐

最新推荐

recommend-type

运用哈夫曼编码压缩解压文件源代码

运用哈夫曼编码压缩解压文件源代码,代码有详细的注释,很好的压缩解压的源代码
recommend-type

哈夫曼编码-译码器课程设计报告.docx

设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。 基本要求: (1)将权值数据存放在数据文件(文件名为data.txt,位于执行程序的当前目录中) (2)分别采用动态和静态存储...
recommend-type

哈夫曼编码压缩解压缩程序(CPP写的)

哈夫曼编码压缩解压缩程序(CPP写的) 多媒体课程设计中也许能用的到 希望能帮到能用的到的人
recommend-type

三元哈夫曼编码 哈夫曼树

详细描述了哈夫曼树的构造方法,同时推广到三元哈夫曼编码,并用C语言于VC++上实现
recommend-type

哈夫曼编码(贪心算法)报告.doc

算法设计与分析实验报告,附已通过源码,供学习参考,共勉♪ 目录摘要如下: 1.问题描述 2.实验目的 3.实验原理 4.实验设计 ...(包括输入格式、算法、输出格式) ...(除了截图外,实验结果还用图表进行了分析) ...
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

机器学习怎么将excel转为csv文件

机器学习是一种利用计算机算法和统计数据的方法来训练计算机来进行自动学习的科学,无法直接将excel文件转为csv文件。但是可以使用Python编程语言来读取Excel文件内容并将其保存为CSV文件。您可以使用Pandas库来读取Excel文件,并使用to_csv()函数将其保存为CSV格式。以下是代码示例: ```python import pandas as pd # 读取 Excel 文件 excel_data = pd.read_excel('example.xlsx') # 将数据保存为 CSV 文件 excel_data.to_csv('example.csv', index=
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。