在何种情况下,哈弗曼编码实验报告与行程编码哪个算法压缩比率更大

随笔 - 34&
文章 - 2&评论 - 49&trackbacks - 0
  哈夫曼编码(Huffman coding)是一种可变长的前缀码。哈夫曼编码使用的算法是David A. Huffman还是在MIT的学生时提出的,并且在1952年发表了名为《A Method for the Construction of Minimum-Redundancy Codes》的文章。编码这种编码的过程叫做哈夫曼编码,它是一种普遍的熵编码技术,包括用于无损数据压缩领域。由于哈夫曼编码的运用广泛,本文将简要介绍:
哈夫曼编码的编码(不包含解码)原理
代码(java)实现过程
一、哈弗曼编码原理
  哈夫曼编码使用一种特别的方法为信号源中的每个符号设定二进制码。出现频率更大的符号将获得更短的比特,出现频率更小的符号将被分配更长的比特,以此来提高数据压缩率,提高传输效率。具体编码步骤主要为,
  1、统计:
  在开始编码时,通常都需要对信号源,也就是本文的一段文字,进行处理,计算出每个符号出现的频率,得到信号源的基本情况。接下来就是对统计信息进行处理了
  2、构造优先对列:
  把得到的符号添加到优先队列中,此优先队列的进出逻辑是频率低的先出,因此在设计优先队列时需要如此设计,如果不熟悉优先队列,请阅读相关书籍,在此不做过多概述。得到包含所有字符的优先队列后,就是处理优先队列中的数据了。
  3、构造哈夫曼树:
  哈夫曼树是带权值得二叉树,我们使用的哈夫曼树的权值自然就是符号的频率了,我们构建哈夫曼树是自底向上的,先构建叶子节点,然后逐步向上,最终完成整颗树。先把队列中的一个符号出列,也就是最小频率的符号,,然后再出列一个符号。这两个符号将作为哈夫曼树的节点,而且这两个节点将作为新节点,也就是它们父节点,的左右孩子节点。新节点的频率,即权值,为孩子节点的和。把这个新节点添加到队列中(队列会重新根据权值排序)。重复上面的步骤,两个符号出列,构造新的父节点,入列&&直到队列最后只剩下一个节点,这个节点也就是哈夫曼树的根节点了。
  4、为哈弗曼树编码:
  哈夫曼树的来自信号源的符号都是叶子节点,需要知道下。树的根节点分配比特0,左子树分配0,右字数分配1。然后就可以得到符号的码值了。
二、示例(转自的)
  假如我有A,B,C,D,E五个字符,出现的频率(即权值)分别为5,4,3,2,1,那么我们第一步先取两个最小权值作为左右子树构造一个新树,即取1,2构成新树,其结点为1+2=3,如图:
  虚线为新生成的结点,第二步再把新生成的权值为3的结点放到剩下的集合中,所以集合变成{5,4,3,3},再根据第二步,取最小的两个权值构成新树,如图:
再依次建立哈夫曼树,如下图:
其中各个权值替换对应的字符即为下图:
所以各字符对应的编码为:A-&11,B-&10,C-&00,D-&011,E-&010
如下图也可以加深大家的理解(图片来自于)
下面的这个图片是互动示例的截图,来自,输入符号就会动态展示出树的构建,有兴趣的朋友可以去看看
三、 代码实现
先是设计一个用于节点比较的接口
1 package com.
3 //用来实现节点比较的接口
4 public interface Compare&T& {
boolean less(T t);
然后写一个哈夫曼树节点的类,主要是用于储存符号信息的,实现上面的接口,get、set方法已经省略了
1 package com.
3 public class Node implements Compare&Node&{
//节点的优先级
private int
//字符出现的频率(次数)
private int
//文本中出现的字符串
private Node leftN
private Node rightN
//对应的二进制编码
public Node(){
public Node(int nice, String str, int count){
this.nice =
this.str =
this.count =
//把节点(权值,频率)相加,返回新的节点
public Node add(Node node){
Node n = new Node();
n.nice = this.nice + node.
n.count = this.count + node.
public boolean less(Node node) {
return this.nice & node.
public String toString(){
return String.valueOf(this.nice);
设计一个优先队列
1 package com.
3 import java.util.L
5 public class PriorityQueue&T extends Compare&T&& {
public List&T& list = null;
public PriorityQueue(List&T& list){
this.list =
public boolean empty(){
return list.size() == 0;
public int size(){
return list.size();
//移除指定索引的元素
public void remove(int number){
int index = list.indexOf(number);
if (-1 == index){
System.out.println("data do not exist!");
list.remove(index);
//每次删除一个元素都需要重新构建队列
buildHeap();
//弹出队首元素,并把这个元素返回
public T pop(){
//由于优先队列的特殊性,第一个元素(索引为0)是不使用的
if (list.size() == 1){
return null;
T first = list.get(1);
list.remove(1);
buildHeap();
//加入一个元素到队列中
public void add(T object){
list.add(object);
buildHeap();
//维护最小堆
private List&T& minHeap(List&T& list, int position, int heapSize){
int left = 2 *
//得到左孩子的位置
int right = left + 1;
//得到右孩子的位置
//min储存最小值的位置,暂时假定当前节点是最小节点
//寻找最小节点
if (left & heapSize
list.get(left).less(list.get(min))){
if (right & heapSize && list.get(right).less(list.get(min))){
if (min != position){
exchange(list, min, position);
//交换当前节点与最小节点的位置
minHeap(list, min, heapSize);
//重新维护最小堆
//交换元素位置
private List&T& exchange(List&T& list, int former, int latter){
T temp = list.get(former);
list.set(former, list.get(latter));
list.set(latter, temp);
//构建最小堆
public List&T& buildHeap(){
for (i = list.size() - 1; i & 0; i--){
minHeap(list, i, list.size());
最后是用一个类构建哈夫曼树
1 package com.
3 import java.util.ArrayL
4 import java.util.HashM
5 import java.util.L
6 import java.util.M
8 public class Huffman {
//优先队列
private PriorityQueue&Node& priorQ
//需要处理的文本
private String[]
//文本处理后的统计信息
private Map&String, Integer&
//huffman编码最终结果
private Map&String, String&
public Huffman(String text) {
this.text = text.split("\\W+");
private void init() {
statistics = new HashMap&String, Integer&();
result = new HashMap&String, String&();
//获取字符串统计信息,得到如"abc":3,"love":12等形式map
private void getStatistics() {
for (String c : text) {
if (statistics.containsKey(c)) {
count = statistics.get(c);
statistics.put(c, count);
statistics.put(c, 1);
//构建huffman树
private void buildTree() {
List&Node& list = new ArrayList&Node&();
list.add(new Node(2222, "123", 2222));
//因为优先队列的特殊性,添加这个不使用的节点
//把字符串信息储存到节点中,并把节点添加到arrayList中
for (String key : statistics.keySet()) {
Node leaf = new Node(statistics.get(key), key, statistics.get(key));
list.add(leaf);
Node tree = null;
//用于储存指向huffman树根节点的指针
priorQueue = new PriorityQueue&Node&(list);
//以上面节点为元素,构建优先队列
priorQueue.buildHeap();
Node first = null;
Node second = null;
Node newNode = null;
first = priorQueue.pop();
//取出队首的元素,作为左孩子节点
second = priorQueue.pop();
//取出队首的元素,作为右孩子节点
newNode = first.add(second);
//构建父节点
priorQueue.add(newNode);
//把父节点添加到队列中
newNode.setLeftNode(first);
newNode.setRightNode(second);
tree = newN
//把tree指向新节点
} while (priorQueue.size() & 2);
//由于队列中有一个元素是不使用的,所以队列只剩最后一个元素(实际就是队列只有2个元素)时就该退出循环了。
//最后剩下一个节点是根节点,把它取出来,并拼装树
Node root = priorQueue.pop();
root.setCode("0");
root.setLeftNode(tree.getLeftNode());
root.setRightNode(tree.getRightNode());
tree = null;
setCodeNum(root);
//遍历树,为每个节点编码
System.out.println("----------------------------");
System.out.println(result);
public void buildHuffman(){
getStatistics();
//收集统计信息
buildTree();
for (String c : statistics.keySet()) {
System.out.println(c + ":" + statistics.get(c));
private void setCodeNum(Node tree){
if(null == tree){
Node left = tree.getLeftNode();
Node right = tree.getRightNode();
if (left !=null){
left.setCode("0" + tree.getCode());
//左孩子的码为0
if (statistics.containsKey(left.getStr())){
//如果节点在统计表里,把它添加到result中
result.put(left.getStr(), left.getCode());
if (right != null){
right.setCode("1" + tree.getCode());
//右孩子的码为1
if (statistics.containsKey(right.getStr())){
//如果节点在统计表里,把它添加到result中
result.put(right.getStr(), right.getCode());
setCodeNum(left);
setCodeNum(right);
&注意:代码实现的提供主要是为了概要介绍哈夫曼编码的实现过程,部分代码逻辑并为深思,效率也略低,请大家只做参考,并多参考其他人的代码。
参考文章:
延伸阅读:
  这个网站是由一群用它们的话说是为&对编程狂热或者有兴趣的人建立的&,提供了很多算法有关的互动的例子,以及一些小程序
  这是一个建立哈夫曼树的简明教程
  提供了多语言的哈夫曼树实现,包括c, c++, java, c#, python, lisp等。有兴趣的朋友可以参考下,看看国外的码农是怎么玩哈夫曼树的。
阅读(...) 评论()博客分类:
//这是我一个学长的,我看了好久才明白,给大家分享,这里的代码只是一个压缩方法的,还有
//一些类已经上传(测试类,结构类都在文件里面),需要可以下载,这个算法没有用递归遍历整个文件夹,所以之只能压缩
//一个文件,下面是主要压缩步骤:
//整个压缩文件的内容:(写入顺序)
* 1.将原文件大小写入文件 dos.writeInt(fileSize);
* 2.将码表的大小写入文件 dos.writeInt(mapSize);
* 3.将每个字节写入文件fos.write(listBy.get(i));
* 4.将每个字节对应的哈夫曼编码大小写入文件fos.write(codeSize);
* 5.将每个字符对应的哈夫曼编码写入文件dos.writeChars(hfmcode_next);
* 6.写入压缩后的字节数组的大小
* 7.写入文件内容
import java.io.BufferedW
import java.io.F
import java.io.FileW
import java.io.IOE
import java.util.HashM
import java.util.L
import javax.swing.tree.TreeN
* 整个压缩文件的内容:(写入顺序)
* 1.将原文件大小写入文件 dos.writeInt(fileSize);
* 2.将码表的大小写入文件 dos.writeInt(mapSize);
* 3.将每个字节写入文件fos.write(listBy.get(i));
* 4.将每个字节对应的哈夫曼编码大小写入文件fos.write(codeSize);
* 5.将每个字符对应的哈夫曼编码写入文件dos.writeChars(hfmcode_next);
* 6.写入压缩后的字节数组的大小
* 7.写入文件内容
* @author yan
public class yasu {
private String hashcode_path="D:\\实验文件夹\\HashCode.txt";//存储所有字节哈弗曼编码01串
* 读取文件
* @param path
* @return:将文件的内容以字节数组的样式返回
public static byte[] readFile(String path) {
byte[] dataByte =
java.io.FileInputStream fis = new java.io.FileInputStream(path);
//int size = fis.available();// 可读的字节数
File f = new File(path);
long size1=f.length();//这样子也可以获取源文件的大小,并且还很准确。
int size=(int)size1;
dataByte = new byte[size];
fis.read(dataByte);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return dataB
* 将码表的相关信息写入文件
* @param fileSize
:原文件大小
* @param map
:存放码表的map
* @param listCh
:存放关键码的字符队列
* @param path
* @throws Exception
public static void writeMap(int fileSize,
java.util.HashMap&Byte, String& map, List&Byte& listBy, String path)
throws Exception {
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);
dos.writeInt(fileSize);//1. 将原文件大小写入文件
int mapSize = map.size();// 码表的大小
dos.writeInt(mapSize);// 2.将码表的大小写入文件
for (int i = 0; i & mapS i++) {
fos.write(listBy.get(i));// 3.将每个字节写入文件
String hfmcode_next = map.get(listBy.get(i));// 得到每个字节对应的哈夫曼编码
byte codeSize = (byte) hfmcode_next.length();
fos.write(codeSize);// 4.将每个字节对应的哈夫曼编码大小写入文件
dos.writeChars(hfmcode_next);// 5.将每个字符对应的哈夫曼编码写入文件
dos.flush();
fos.close();
* 将压缩好的字节数组写入文件
* @param b
:压缩好的字节数组
* @param path
public static void writeFile(byte[] b, String path) {
java.io.FileOutputStream fos = new java.io.FileOutputStream(path,
java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);
// 写入字节数组的大小
dos.writeInt(b.length);
fos.write(b);
fos.flush();
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
* 将10字符串以8个为一组转化为一个字节数组
* @param str
//String -&char[]-&byte( char数组转换成byte数组 然后把一个8个字节大小的byte数组转换成一个2进制的值,然后强制转型为byte
实现压缩。。。结果得到一个byte类型的值)-&
private byte[] StringToByteArray(String str) {
char[] c = str.toCharArray();// 将字节串str转化为字符数组c
int len = c.// 字符串字符的个数
String s = "";
byte[]//存放已经转换成字节的01串
if (len % 8 == 0) {// 如果字符串的长度能被8整除
lenByte = len / 8 + 1;//+1是因为最后一个要存放补0的个数
b = new byte[lenByte];
for (int i = 0; i & lenByte - 1; i++) {
for (int j = i * 8; j & (i + 1) * 8; j++) {
c_next = c[j];
s = s + c_//第i个组的01串,每8个一组(分离出8个01串字符,)
//System.out.println("第" + i + "个字符串:" + s);
System.out.println("进入转化8个01串的方法");
b[i] = CharArrayToByte(s);//把一组01字符串转化成一个字节
//System.out.println("第" + i + "个字符串转化为字节后的值:" + b[i]);
b[lenByte - 1] = 0;// 字节数组的最后一个存放补0的个数
} else {// 如果字符串的长度不能被8整除
lenByte = len / 8 + 2;
b = new byte[lenByte];
int remainder = len % 8;// 求出除8的余数
int zeroNum = 8 -// 补0的个数
//System.out.println("补0数:" + zeroNum);
//System.out.println("原字符串:" + str);
for (int i = 0; i & zeroN i++) {
str = str + '0';// 在字符串后面补0
//System.out.println("补0后的字符串:" + str);
c = str.toCharArray();
//System.out.println("补0后的字符串的字符个数:" + c.length);
for (int i = 0; i & lenByte - 1; i++) {
for (int j = i * 8; j & (i + 1) * 8; j++) {
c_next = c[j];
s = s + c_
//System.out.println("第" + i + "个字符串:" + s);
b[i] = CharArrayToByte(s);
//System.out.println("第" + i + "个字符串转化为字节后的值:" + b[i]);
b[lenByte - 1] = (byte) zeroN// 字节数组的最后一个存放补0的个数
* 将8字符串(8个字节)转化为一个字节,(其实这里便是压缩过程。。。)
* 把一个8个字节大小的byte数组转换成一个2进制的值,然后强制转型为byte
实现压缩。。。
* @param str: 传入的8字符串
* @return: 一个字节
private byte CharArrayToByte(String str) {
char[] c = str.toCharArray();// 将字符串str转化为字符数组c
int len = c.
byte[] b = new byte[len];
byte value = 0;
byte value_
for (int i = 0; i & i++) {
b[i] = Byte.parseByte(c[i] + "");//此方法将返回由十进制参数表示的字节值
// System.out.println(b[i]);
//把一个8个字节大小的byte数组转换成一个2进制的值,然后强制转型为byte
8位就是2的8次方,则最大为256
实现压缩。。。。。
for (int i = 0; i & i++) {
value_next = (byte) (b[i] * Math.pow(2, len - i - 1));// 幂计算,括号里面计算一组01串的二进制数
value = (byte) (value + value_next);
//b[i] * Math.pow(2, len - i - 1)这个计算的是一个没有符号位的8位01串,它的范围是0到256,但是byte是-128到127,所以会出现负值
//在解压的时候转换成int类型时候+256
* 把哈弗曼编码01串存入文件
public static void Save_hashcode(String path,String hfmcode){
FileWriter fw=new FileWriter(path);
BufferedWriter bw=new BufferedWriter(fw);
bw.write(hfmcode);
bw.flush();
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
* 压缩文件
* @param path1
:原文件路径
* @param path2
:压缩后的文件路径
* @throws Exception
public void CompressFile(String path1, String path2) throws Exception {
// 从文件中得到字节数组
System.out.println("进入压缩方法");
byte[] b = yasu.readFile(path1);
int b_size = b.// 原文件大小
byte[] b_// 字节数组,存放压缩的字符串
String hfmcode = "";// 文件内所有字节的哈夫曼编码
String hfmcode_// 文件中每个字节的哈夫曼编码
// ********上面那么多就是想要得到码表和存放关键码队列
Tree hfm = new Tree();
HashMap&Byte, String& map = hfm.M(path1);//这个是存有byte和相应的编码的haspmap键值对
// 接下来获得存放关键码的队列(存有字节名称的list集合)
List&Byte& listBy = hfm.L(path1);
for (int i = 0; i & b_ i++) {
// 得到每个字节的哈夫曼编码
hfmcode_next = map.get(b[i]); // 字节b[i]对应的哈夫曼编码
// System.out.println("第" + i + "个: " + b[i] + "的编码:" + hfmcode_next);
hfmcode = hfmcode + hfmcode_// 将每个字节的哈夫曼编码依次相加为一个01字符串
// hfmcode存放源文件所有字节一一对应的哈夫曼编码
//System.out.println("01串大小:" + hfmcode.length());
//System.out.println("01串:" + hfmcode);
char[] ch = hfmcode.toCharArray(); // 将源文件的哈夫曼编码转化成字符数组
//System.out.println("01串的大小:" + ch.length);
// 将源文件的哈夫曼编码转化 得到对应的字节数组,这个方法StringToByteArray(hfmcode);
//实现了将8个byte字节转换成一个2进制数然后又转换为byte,实现压缩
b_compress = StringToByteArray(hfmcode);
//for (int i = 0; i & b_compress. i++) {
//System.out.println("第" + i + "个字节" + b_compress[i]);
System.out.println("进入写入***********");
// 1.将文件大小和码表相关信息写入文件
writeMap(b_size, map, listBy, path2);
// 2.将字节数组写入文件
writeFile(b_compress, path2);
Save_hashcode(hashcode_path,hfmcode);
System.out.println("完成!!");
下载次数: 15
浏览: 41885 次
来自: 长沙
cs6641468 写道同学, 建议还是看看官方文档。你肯定是 ...
cs6641468 写道同学, 建议还是看看官方文档。你肯定是 ...
同学, 建议还是看看官方文档。你肯定是百度找了一些抄来抄去过时 ...
push方法返回的不是移除去的对象吧? 移除的应该是前面和现在 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'5984人阅读
1.老师简直丧心病狂,居然上机作业布置这个,简直了
2.参考网上资料,课本,终于写完了
3.首先将彩色图片转化为位图bmp,然后哈夫曼编码压缩,然后解压缩,我真是醉了(有什么用)
4.具体用法
BMPToGray 彩色图片转灰度图&
encode 压缩
&decode方法解压缩
彩色图片必须是位图(bmp),不是的格式工厂转化
然后每一个方法输入两个参数,分别为输入文件名,和输出文件名
compressor.h文件
#pragma pack(1)
typedef struct BMPHeader
unsigned char bfType[2];//文件格式
unsigned long bfS//文件大小
unsigned short bfReserved1;//保留
unsigned short bfReserved2;
unsigned long bfOffB //DIB数据在文件中的偏移量
typedef struct BMPInfo
unsigned long biS//该结构的大小
long biW//文件宽度
long biH//文件高度
unsigned short biP//平面数
unsigned short biBitC//颜色位数
unsigned long biC//压缩类型
unsigned long biSizeI//DIB数据区大小
long biXPixPerM
long biYPixPerM
unsigned long biClrU//多少颜色索引表
unsigned long biClrI//多少重要颜色
typedef struct RGBQuad
unsigned char rgbB //蓝色分量亮度
unsigned char rgbG//绿色分量亮度
unsigned char rgbR//红色分量亮度
unsigned char rgbR
#pragma pack()
typedef struct{
typedef struct Node{
// 字符对应的哈夫曼编码
int parent, lchild,
Node(){parent=0;}
} HufNode,*HufT
class Compressor
unsigned char RGBData[4000][3];
unsigned char GrayData[4000];
FILE * fpBMP,* fpG
int BmpToGray(const char *,const char *);
int decode(const char *,const char *);
int encode(const char *,const char *);
int openFile(const char *,const char *);
void select(HufNode*,unsigned int,int *);
void createTree(HufNode *,unsigned int,unsigned int);
void createCode(HufNode *,unsigned);
closeFile();
compressor.cpp文件
#include&iostream&
#include&cstdio&
#include&cstring&
#include&algorithm&
#include&compressor.h&
int Compressor::openFile(const char *in,const char *out){
if(!(fpBMP=fopen(in,&rb&)))
printf(&打开文件失败\n&);
if(!(fpGray=fopen(out,&wb&)))
printf(&创建文件失败\n&);
void Compressor::select(HufNode *huf_tree, unsigned int n, int *s1)
unsigned long m=ULONG_MAX;
for(int i = 0;i&n;i++)
if(!huf_tree[i].parent&&huf_tree[i].weight&m)
m= huf_tree[i].
huf_tree[*s1].parent=1;
void Compressor::createTree(HufNode *huf_tree, unsigned int char_kinds, unsigned int node_num)
int s1, s2;
for(i = char_ i & node_ ++i)
select(huf_tree,i, &s1);
select(huf_tree,i,&s2);
huf_tree[s1].parent = huf_tree[s2].parent =
huf_tree[i].lchild = s1;
huf_tree[i].rchild = s2;
huf_tree[i].weight = huf_tree[s1].weight + huf_tree[s2].
void Compressor::createCode(HufNode *huf_tree, unsigned char_kinds)
int cur, next,
char *code_tmp = new char[256];
code_tmp[255] = '\0';
for(int i=0; i&char_i++)
index = 256-1;
for(cur=i,next=huf_tree[i].next!= 0;cur=next,next=huf_tree[cur].parent)
if(huf_tree[next].lchild == cur)
code_tmp[--index] = '0';
code_tmp[--index] = '1';
huf_tree[i].code = new char[256-index];
strcpy(huf_tree[i].code, &code_tmp[index]);
delete [] code_
void Compressor::closeFile(){
fclose(fpBMP);
fclose(fpGray);
bool cmp(TmpNode &a,TmpNode &b){
return a.weight&b.
int Compressor::encode(const char * in,const char *out){
if(!openFile(in,out)) return 0;
TmpNode *tmp_nodes= new TmpNode[256];
for(int i=0;i&256;i++){
tmp_nodes[i].weight=0;
tmp_nodes[i].uch=(unsigned char)i;
unsigned char tmp_
unsigned long file_len=0,node_
unsigned int char_kinds=256;
HufNode *huf_
while(fread(&tmp_char,1,1,fpBMP)){
file_len++;
tmp_nodes[tmp_char].weight++;
sort(tmp_nodes,tmp_nodes+256,cmp);
for(int i=0;i&char_i++)
if(!tmp_nodes[i].weight)
char_kinds=i;
if(char_kinds==1){
fwrite((char *)&char_kinds, sizeof(unsigned int), 1, fpGray);
fwrite((char *)&tmp_nodes[0].uch,1, 1, fpGray);
fwrite((char *)&tmp_nodes[0].weight, sizeof(unsigned long), 1, fpGray);
node_num=2*char_kinds-1;
huf_tree = new HufNode[node_num];
for(int i=0; i&char_ i++)
huf_tree[i].uch = tmp_nodes[i].
huf_tree[i].weight = tmp_nodes[i].
createTree(huf_tree, char_kinds, node_num);
createCode(huf_tree, char_kinds);
fwrite((char *)&char_kinds, sizeof(unsigned int), 1, fpGray);
for(int i=0;i&char_i++)
fwrite((char *)&huf_tree[i].uch, sizeof(unsigned char), 1, fpGray);
fwrite((char *)&huf_tree[i].weight, sizeof(unsigned long), 1, fpGray);
fwrite((char *)&file_len, sizeof(unsigned long), 1, fpGray);
fclose(fpBMP);
fpBMP = fopen(in,&rb&);
unsigned char char_
char code_buf[256] = &\0&;
fread((char *)&char_temp, sizeof(unsigned char), 1, fpBMP);
// 每次读取8bits
while(!feof(fpBMP))
for(int i=0; i & char_ ++i)
if(char_temp == huf_tree[i].uch)
strcat(code_buf, huf_tree[i].code);
while(strlen(code_buf) &= 8)
char_temp =0;
for(int i = 0; i & 8; ++i)
char_temp=(char_temp&&1)|(code_buf[i]-'0');
fwrite((char *)&char_temp, sizeof(unsigned char), 1, fpGray);
// 将字节对应编码存入文件
strcpy(code_buf, code_buf+8);
// 编码缓存去除已处理的前八位
fread((char *)&char_temp, sizeof(unsigned char), 1, fpBMP);
// 每次读取8bits
unsigned int l=strlen(code_buf);
char_temp =0;
for(int i = 0; i &l; ++i)
char_temp=(char_temp&&1)|(code_buf[i]-'0');
char_temp &&= 8-l;
fwrite((char *)&char_temp, sizeof(unsigned char), 1, fpGray);
// 存入最后一个字节
for(int i = 0; i & char_ ++i)
delete [] huf_tree[i].
delete []huf_
delete [] tmp_
closeFile();
int Compressor::decode(const char * in,const char *out){
if(!openFile(in,out)) return 0;
unsigned long file_
unsigned int char_
unsigned int node_
HufTree huf_
unsigned char code_
// 保存根节点索引,供匹配编码使用
fread((char *)&char_kinds, sizeof(unsigned int), 1, fpBMP);
if (char_kinds == 1)
fread((char *)&code_temp, sizeof(unsigned char), 1, fpBMP);
fread((char *)&file_len, sizeof(unsigned long), 1, fpBMP);
while (file_len--)
fwrite((char *)&code_temp, sizeof(unsigned char), 1,fpGray);
node_num = 2 * char_kinds - 1;
huf_tree = new HufNode[node_num];
for(i = 0; i & char_ ++i)
fread((char *)&huf_tree[i].uch, sizeof(unsigned char), 1, fpBMP);
fread((char *)&huf_tree[i].weight, sizeof(unsigned long), 1, fpBMP);
createTree(huf_tree, char_kinds, node_num);
fread((char *)&file_len, sizeof(unsigned long), 1, fpBMP);
root = node_num-1;
//解码 解码 解码 开始了 现在哈弗曼树已经构建好了
while(fread((char *)&code_temp, sizeof(unsigned char), 1, fpBMP))
//现在先取8bits数据,然后一位一位的找
for(i = 0;i&8;++i)
//128=100000,就是查看最开始的一位是不是0啦,是的话就在左边 不是自然有孩子
if(code_temp&128)
root = huf_tree[root].
root = huf_tree[root].
//假如我们找到了叶子 自然就知道是啥了 写入文件就好了
if(root& char_kinds)
fwrite((char *)&huf_tree[root].uch, sizeof(unsigned char), 1, fpGray);
root = node_num-1;
// 复位为根索引,匹配下一个字符
code_temp &&= 1;
// 将编码缓存的下一位移到最高位,供匹配
delete [] huf_
closeFile();
int Compressor::BmpToGray(const char *in,const char *out){
if(!openFile(in,out)) return 0;
header=new H
info=new I
quad=new Quad[256];
fread(header,sizeof(Header),1,fpBMP);
fread(info,sizeof(Info),1,fpBMP);
info-&biBitCount=8;
info-&biSizeImage=( (info-&biWidth*3+3)/4 ) * 4*info-&biH
header-&bfOffBits = sizeof(Header)+sizeof(Info)+256*sizeof(Quad);
header-&bfSize = header-&bfOffBits + info-&biSizeI
int i,j,k;
for(i=0;i&256;i++)
quad[i].rgbBlue=quad[i].rgbGreen=quad[i].rgbRed=i;
fwrite(header,sizeof(Header),1,fpGray);
fwrite(info,sizeof(Info),1,fpGray);
fwrite(quad,sizeof(Quad),256,fpGray);
for (i=0;i&info-&biHi++ )
for(j=0;j&(info-&biWidth+3)/4*4;j++)
fread(&RGBData[j],1,3,fpBMP);
GrayData[j]=RGBData[j][0] * 0.114 +RGBData[j][1] * 0.587 +RGBData[j][2] * 0.299;
fwrite(GrayData,j,1,fpGray);
closeFile();
void test(){
compressor.BmpToGray(&in.bmp&,&out.bmp&);
cout&&&彩色图片转化为灰度图完成&&&
compressor.encode(&out.bmp&,&encode.dat&);
cout&&&压缩文件完成&&&
compressor.decode(&encode.dat&,&decode.bmp&);
cout&&&解压缩文件完成&&&
cout&&&Test Over!&&&
int main()
好运,晚安。。。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:33819次
排名:千里之外
原创:32篇
评论:22条
(1)(3)(3)(1)(6)(1)(15)(3)}

我要回帖

更多关于 行程长度编码算法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信