Huffman编码及解码.docx

上传人:b****5 文档编号:6775788 上传时间:2023-01-10 格式:DOCX 页数:20 大小:20.13KB
下载 相关 举报
Huffman编码及解码.docx_第1页
第1页 / 共20页
Huffman编码及解码.docx_第2页
第2页 / 共20页
Huffman编码及解码.docx_第3页
第3页 / 共20页
Huffman编码及解码.docx_第4页
第4页 / 共20页
Huffman编码及解码.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

Huffman编码及解码.docx

《Huffman编码及解码.docx》由会员分享,可在线阅读,更多相关《Huffman编码及解码.docx(20页珍藏版)》请在冰豆网上搜索。

Huffman编码及解码.docx

Huffman编码及解码

Huffman编码图像解码

*********************/

//读入编码图像

boolreadHuffman(char*Name)

{

inti,j;

charNameStr[100];

//读取Huffman编码信息和编码树

strcpy(NameStr,Name);

strcat(NameStr,".bpt");

FILE*fin=fopen(NameStr,"r");

if(fin==0){

printf("未找到指定文件!

\n");

return0;

}

fscanf(fin,"%d%d%d",&NodeStart,&NodeNum,&InfLen);

//printf("%d%d%d\n",NodeStart,NodeNum,InfLen);

for(i=0;i

fscanf(fin,"%d%d%d",&node[i].color,&node[i].lson,&node[i].rson);

//printf("%d%d%d\n",node[i].color,node[i].lson,node[i].rson);

}

//二进制读方式打开指定的图像文件

strcpy(NameStr,Name);

strcat(NameStr,".bhd");

FILE*fp=fopen(NameStr,"rb");

if(fp==0){

printf("未找到指定文件!

\n");

return0;

}

//跳过位图文件头结构BITMAPFILEHEADER

fseek(fp,sizeof(BITMAPFILEHEADER),0);

//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中

BITMAPINFOHEADERhead;

fread(&head,sizeof(BITMAPINFOHEADER),1,fp);

//获取图像宽、高、每像素所占位数等信息

bmpWidth=head.biWidth;

bmpHeight=head.biHeight;

biBitCount=head.biBitCount;

//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)

intlineByte=(bmpWidth*biBitCount/8+3)/4*4;

//灰度图像有颜色表,且颜色表表项为256

if(biBitCount==8){

//申请颜色表所需要的空间,读颜色表进内存

pColorTable=newRGBQUAD[256];

fread(pColorTable,sizeof(RGBQUAD),256,fp);

}

//申请位图数据所需要的空间,读位图数据进内存

pBmpBuf=newunsignedchar[lineByte*bmpHeight];

fread(pBmpBuf,1,InfLen/8,fp);

//关闭文件

fclose(fp);

return1;

}

voidHuffmanDecode()

{

//获取编码信息

inti,j,tmp;

intlineByte=(bmpWidth*biBitCount/8+3)/4*4;

for(i=0;i

{

j=i*8+7;

tmp=*(pBmpBuf+i);

while(tmp>0)

{

ImgInf[j]=tmp%2;

tmp/=2;

j--;

}

}

/*for(i=0;i

printf("%d",ImgInf[i]);

printf("\n");*/

//解码

intp=NodeStart;//遍历指针位置

j=0;

i=0;

do

{

if(node[p].color>=0)

{

*(pBmpBuf+j)=node[p].color;

//printf("%d",*(pBmpBuf+j));

j++;

p=NodeStart;

}

if(ImgInf[i]==1)

p=node[p].lson;

elseif(ImgInf[i]==0)

p=node[p].rson;

i++;

}while(i<=InfLen);

//printf("\nj:

%d\n",j);

}

/*********************

Huffman编码

*********************/

//Huffman编码初始化

voidHuffmanCodeInit()

{

inti;

for(i=0;i<256;i++)//灰度值记录清零

Num[i]=0;

//初始化哈夫曼树

for(i=0;i<600;i++)

{

node[i].color=-1;

node[i].lson=node[i].rson=-1;

node[i].num=-1;

node[i].mark=0;

}

NodeNum=0;

}

//深搜遍历Huffman树获取编码值

charCodeTmp[300];

voiddfs(intpos,intlen)

{

//遍历左儿子

if(node[pos].lson!

=-1)

{

CodeTmp[len]='1';

dfs(node[pos].lson,len+1);

}

else

{

if(node[pos].color!

=-1)

{

CodeLen[node[pos].color]=len;

CodeTmp[len]='\0';

strcpy(CodeStr[node[pos].color],CodeTmp);

}

}

//遍历右儿子

if(node[pos].lson!

=-1)

{

CodeTmp[len]='0';

dfs(node[pos].rson,len+1);

}

else{

if(node[pos].color!

=-1)

{

CodeLen[node[pos].color]=len;

CodeTmp[len]='\0';

strcpy(CodeStr[node[pos].color],CodeTmp);

}

}

}

//寻找值最小的节点

intMinNode()

{

inti,j=-1;

for(i=0;i

if(!

node[i].mark)

if(j==-1||node[i].num

j=i;

if(j!

=-1)

{

NodeStart=j;

node[j].mark=1;

}

returnj;

}

//编码主函数

voidHuffmanCode()

{

inti,j,k,a,b;

for(i=0;i<256;i++)

{//创建初始节点

Feq[i]=(float)Num[i]/(float)(bmpHeight*bmpWidth);//计算灰度值频率

if(Num[i]>0)

{

node[NodeNum].color=i;

node[NodeNum].num=Num[i];

node[NodeNum].lson=node[NodeNum].rson=-1;//叶子节点无左右儿子

NodeNum++;

}

}

while

(1)

{//找到两个值最小的节点,合并成为新的节点

a=MinNode();

if(a==-1)

break;

b=MinNode();

if(b==-1)

break;

//构建新节点

node[NodeNum].color=-1;

node[NodeNum].num=node[a].num+node[b].num;

node[NodeNum].lson=a;

node[NodeNum].rson=b;

NodeNum++;

//node[a].mark=node[b].mark=1;

}

//根据建好的Huffman树编码(深搜实现)

dfs(NodeStart,0);

//屏幕输出编码

intsum=0;

printf("Huffman编码信息如下:

\n");

for(i=0;i<256;i++)

if(Num[i]>0)

{

sum+=CodeLen[i]*Num[i];

printf("灰度值:

%3d频率:

%f码长:

%2d编码:

%s\n",i,Feq[i],CodeLen[i],CodeStr[i]);

}

//printf("原始总码长:

%d\n",bmpWidth*bmpHeight*8);

//printf("Huffman编码总码长:

%d\n",sum);

//printf("压缩比:

%.3f:

1\n",(float)(bmpWidth*bmpHeight*8)/(float)sum);

//记录图像信息

InfLen=0;

intlineByte=(bmpWidth*biBitCount/8+3)/4*4;

for(i=0;i

for(j=0;j

{

lpBuf=(unsignedchar*)pBmpBuf+lineByte*i+j;

for(k=0;k

{

ImgInf[InfLen++]=(int)(CodeStr[*(lpBuf)][k]-'0');

}

}

//再编码数据

j=0;

for(i=0;i

{

*(pBmpBuf+j)=Change2to10(i);

i+=8;

j++;

}

}

/******************************

主函数

******************************/

intmain(intargc,char**argv)

{

intord;//命令

charc;

inti,j;

clock_tstart,finish;

inttotal_time;

//CStringstr;

while

(1)

{

printf("本程序提供以下功能\n\n\t1.256色灰度BMP图像Huffman编码\n\t2.Huffman编码BMP文件解码\n\t3.退出\n\n请选择需要执行的命令:

");

scanf("%d%c",&ord,&c);

if(ord==1)

{

printf("\n---256色灰度BMP图像Huffman编码---\n");

printf("\n请输入要编码图像名称:

");

scanf("%s",str);

//读入指定BMP文件进内存

charreadPath[100];

strcpy(readPath,str);

strcat(readPath,".bmp");

if(readBmp(readPath))

{

//输出图像的信息

//printf("\n图像信息:

\nwidth=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpHeight,biBitCount);

intlineByte=(bmpWidth*biBitCount/8+3)/4*4;

if(biBitCount==8)

{

//编码初始化

HuffmanCodeInit();

//计算每个灰度值出现的次数

for(i=0;i

for(j=0;j

{

lpBuf=(unsignedchar*)pBmpBuf+lineByte*i+j;

Num[*(lpBuf)]+=1;

}

//调用编码

start=clock();

HuffmanCode();

finish=clock();

total_time=(finish-start);

printf("识别一张耗时:

 %d毫秒",total_time);

//将图像数据存盘

charwritePath[100];

//保存编码后的bmp

strcpy(writePath,str);

strcat(writePath,"_Huffman.bhd");

saveBmp(writePath,pBmpBuf,bmpWidth,bmpHeight,biBitCount,pColorTable);

//保存Huffman编码信息和编码树

strcpy(writePath,str);

strcat(writePath,"_Huffman.bpt");

saveInfo(writePath,lineByte);

printf("\n编码完成!

编码信息保存在%s_Huffman文件中\n\n",str);

}

else

{

printf("本程序只支持256色BMP编码!

\n");

}

//清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间

delete[]pBmpBuf;

if(biBitCount==8)

delete[]pColorTable;

}

printf("\n-----------------------------------------------\n\n\n");

}

elseif(ord==2)

{

printf("\n---Huffman编码BMP文件解码---\n");

printf("\n请输入要解码文件名称:

");

scanf("%s",str);

//编码解码初始化

HuffmanCodeInit();

if(readHuffman(str))

{//读取文件

HuffmanDecode();//Huffman解码

//将图像数据存盘

charwritePath[100];

//保存解码后的bmp

strcpy(writePath,str);

strcat(writePath,"_Decode.bmp");

InfLen=bmpWidth*bmpHeight*8;

saveBmp(writePath,pBmpBuf,bmpWidth,bmpHeight,biBitCount,pColorTable);

system(writePath);

printf("\n解码完成!

保存为%s_Decode.bmp\n\n",str);

}

printf("\n-----------------------------------------------\n\n\n");

}

elseif(ord==3)

break;

}

return0;/*ANSICrequiresmaintoreturnint.*/

}

/*********************

编码:

 

#include

#include

#include

#include"Windows.h"

#include"math.h"

#include

//几个全局变量,存放读入图像的位图数据、宽、高、颜色表及每像素所占位数(比特)

//此处定义全局变量主要为了后面的图像数据访问及图像存储作准备

unsignedchar*pBmpBuf;//读入图像数据的指针

intbmpWidth;//图像的宽

intbmpHeight;//图像的高

intimgSpace;//图像所需空间

RGBQUAD*pColorTable;//颜色表指针

intbiBitCount;//图像类型

charstr[100];//文件名称

intNum[300];//各灰度值出现的次数

floatFeq[300];//各灰度值出现的频率

unsignedchar*lpBuf;//指向图像像素的指针

unsignedchar*m_pDib;//存放打开文件的DIB

intNodeNum;//Huffman树总节点个数

intNodeStart;//Huffman树起始节点

structNode{//Huffman树节点

intcolor;//记录叶子节点的灰度值(非叶子节点为-1)

intlson,rson;//节点的左右儿子(若没有则为-1)

intnum;//节点的数值(编码依据)

intmark;//记录节点是否被用过(用过为1,没用过为0)

}node[600];

charCodeStr[300][300];//记录编码值

intCodeLen[300];//编码长度

boolImgInf[8000000];//图像信息

intInfLen;//图像信息长度

/***********************************************************************

*函数名称:

*readBmp()

*

*函数参数:

*char*bmpName-文件名字及路径

*

*返回值:

*0为失败,1为成功

*

*说明:

给定一个图像文件名及其路径,读图像的位图数据、宽、高、颜色表及每像素

*位数等数据进内存,存放在相应的全局变量中

***********************************************************************/

boolreadBmp(char*bmpName)

{

//二进制读方式打开指定的图像文件

//FILE*fp=fopen("E:

\ProgramFiles\program\Huffman\1.bmp","rb");

FILE*fp=fopen(bmpName,"rb");

if(fp==0)

{

printf("未找到指定文件!

\n");

return0;

}

//跳过位图文件头结构BITMAPFILEHEADER

fseek(fp,sizeof(BITMAPFILEHEADER),0);

//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中

BITMAPINFOHEADERhead;

fread(&head,sizeof(BITMAPINFOHEADER),1,fp);

//获取图像宽、高、每像素所占位数等信息

bmpWidth=head.biWidth;

bmpHeight=head.biHeight;

biBitCount=head.biBitCount;

//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)

intlineByte=(bmpWidth*biBitCount/8+3)/4*4;

//灰度图像有颜色表,且颜色表表项为256

if(biBitCount==8)

{

//申请颜色表所需要的空间,读颜色表进内存

pColorTable=newRGBQUAD[256];

fread(pColorTable,sizeof(RGBQUAD),256,fp);

}

//申请位图数据所需要的空间,读位图数据进内存

pBmpBuf=newunsignedchar[lineByte*bmpHeight];

fread(pBmpBuf,1,lineByte*bmpHeight,fp);

//关闭文件

fclose(fp);

return1;

}

/***********************************************************************

保存信息

***********************************************************************/

//二进制转十进制

intChange2to10(intpos){

inti,j,two=1;

j=0;

for(i=pos+7;i>=pos;i--){

j+=two*ImgInf[i];

two*=2;

}

returnj;

}

//保存Huffman编码树

intsaveInfo(char*writeP

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 法语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1