#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Windows.h"
#include "math.h"
#include <time.h>
unsigned char *pBmpBuf;
int bmpWidth;
int bmpHeight;
int imgSpace;
RGBQUAD *pColorTable;
int biBitCount;
char str[100];
int Num[300];
float Feq[300];
unsigned char *lpBuf;
unsigned char *m_pDib;
int NodeNum;
int NodeStart;
struct Node
{
int color;
int lson,rson;
int num;
int mark;
} node[600];
char CodeStr[300][300];
int CodeLen[300];
bool ImgInf[8000000];
int InfLen;
* 函数名称:
* readBmp()
*
*函数参数:
* char *bmpName -文件名字及路径
*
*返回值:
* 0为失败,1为成功
*
*说明:给定一个图像文件名及其路径,读图像的位图数据、宽、高、颜色表及每像素
* 位数等数据进内存,存放在相应的全局变量中
***********************************************************************/
bool readBmp(char *bmpName)
{
FILE *fp=fopen(bmpName,"rb");
if(fp==0)
{
printf("未找到指定文件!\n");
return 0;
}
fseek(fp, sizeof(BITMAPFILEHEADER),0);
BITMAPINFOHEADER head;
fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);
bmpWidth = head.biWidth;
bmpHeight = head.biHeight;
biBitCount = head.biBitCount;
int lineByte=(bmpWidth * biBitCount/8+3)/4*4;
if(biBitCount==8)
{
pColorTable=new RGBQUAD[256];
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
pBmpBuf=new unsigned char[lineByte * bmpHeight];
fread(pBmpBuf,1,lineByte * bmpHeight,fp);
fclose(fp);
return 1;
}
保存信息
***********************************************************************/
int Change2to10(int pos)
{
int i,j,two = 1;
j = 0;
for(i = pos + 7; i >= pos; i --)
{
j += two * ImgInf[i];
two *= 2;
}
return j;
}
int saveInfo(char *writePath,int lineByte)
{
int i,j,k;
FILE *fout;
fout = fopen(writePath,"w");
fprintf(fout,"%d %d %d\n",NodeStart,NodeNum,InfLen);
for(i = 0; i < NodeNum; i ++)
{
fprintf(fout,"%d %d %d\n",node[i].color,node[i].lson,node[i].rson);
}
fprintf(fout,"%d",ImgInf[i]);
}
fprintf(fout,"\n");*/
fclose(fout);
return 0;
}
bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height,
int biBitCount, RGBQUAD *pColorTable)
{
if(!imgBuf)
return 0;
int colorTablesize=0;
if(biBitCount==8)
colorTablesize=1024;
int lineByte=(width * biBitCount/8+3)/4*4;
FILE *fp=fopen(bmpName,"wb");
if(fp==0) return 0;
BITMAPFILEHEADER fileHead;
fileHead.bfType = 0x4D42;
fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
+ colorTablesize + lineByte*height;
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;
fileHead.bfOffBits=54+colorTablesize;
fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);
BITMAPINFOHEADER head;
head.biBitCount=biBitCount;
head.biClrImportant=0;
head.biClrUsed=0;
head.biCompression=0;
head.biHeight=height;
head.biPlanes=1;
head.biSize=40;
head.biSizeImage=lineByte*height;
head.biWidth=width;
head.biXPelsPerMeter=0;
head.biYPelsPerMeter=0;
fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);
if(biBitCount==8)
fwrite(pColorTable, sizeof(RGBQUAD),256, fp);
fwrite(imgBuf, InfLen / 8, 1, fp);
fclose(fp);
return 1;
}
Huffman编码图像解码
*********************/
bool readHuffman(char *Name)
{
int i,j;
char NameStr[100];
strcpy(NameStr,Name);
strcat(NameStr,".bpt");
FILE *fin = fopen(NameStr,"r");
if(fin == 0)
{
printf("未找到指定文件!\n");
return 0;
}
fscanf(fin,"%d %d %d",&NodeStart,&NodeNum,&InfLen);
for(i = 0; i < NodeNum; i ++)
{
fscanf(fin,"%d %d %d",&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");
return 0;
}
fseek(fp, sizeof(BITMAPFILEHEADER),0);
BITMAPINFOHEADER head;
fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);
bmpWidth = head.biWidth;
bmpHeight = head.biHeight;
biBitCount = head.biBitCount;
int lineByte=(bmpWidth * biBitCount/8+3)/4*4;
if(biBitCount==8)
{
pColorTable=new RGBQUAD[256];
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
pBmpBuf=new unsigned char[lineByte * bmpHeight];
fread(pBmpBuf,1,InfLen / 8,fp);
fclose(fp);
return 1;
}
void HuffmanDecode()
{
int i,j,tmp;
int lineByte=(bmpWidth * biBitCount/8+3)/4*4;
for(i = 0; i < InfLen / 8; i ++)
{
j = i * 8 + 7;
tmp = *(pBmpBuf + i);
while(tmp > 0)
{
ImgInf[j] = tmp % 2;
tmp /= 2;
j --;
}
}
printf("%d",ImgInf[i]);
printf("\n");*/
int p = NodeStart;
j = 0;
i = 0;
do
{
if(node[p].color >= 0)
{
*(pBmpBuf + j) = node[p].color;
j ++;
p = NodeStart;
}
if(ImgInf[i] == 1)
p = node[p].lson;
else if(ImgInf[i] == 0)
p = node[p].rson;
i ++;
}
while(i <= InfLen);
}
Huffman编码
*********************/
void HuffmanCodeInit()
{
int i;
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;
}
char CodeTmp[300];
void dfs(int pos,int len)
{
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);
}
}
}
int MinNode()
{
int i,j = -1;
for(i = 0; i < NodeNum; i ++)
if(!node[i].mark)
if(j == -1 || node[i].num < node[j].num)
j = i;
if(j != -1)
{
NodeStart = j;
node[j].mark = 1;
}
return j;
}
void HuffmanCode()
{
int i,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 ++;
}
dfs(NodeStart,0);
int sum = 0;
for(i = 0; i < 256; i ++)
if(Num[i] > 0)
{
sum += CodeLen[i] * Num[i];
}
InfLen = 0;
int lineByte=(bmpWidth * biBitCount/8+3)/4*4;
for(i = 0; i < bmpHeight; i ++)
for(j = 0; j < bmpWidth; j ++)
{
lpBuf = (unsigned char *)pBmpBuf + lineByte * i + j;
for(k = 0; k < CodeLen[*(lpBuf)]; k ++)
{
ImgInf[InfLen ++] = (int)(CodeStr[*(lpBuf)][k] - '0');
}
}
j = 0;
for(i = 0; i < InfLen;)
{
*(pBmpBuf + j) = Change2to10(i);
i += 8;
j ++;
}
}
主函数
******************************/
int main(int argc, char** argv)
{
int ord;
char c;
int i,j;
clock_t start,finish;
int total_time;
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);
char readPath[100];
strcpy(readPath,str);
strcat(readPath,".bmp");
if(readBmp(readPath))
{
int lineByte=(bmpWidth * biBitCount/8+3)/4*4;
if(biBitCount==8)
{
HuffmanCodeInit();
for(i = 0; i < bmpHeight; i ++)
for(j = 0; j < bmpWidth; j ++)
{
lpBuf = (unsigned char *)pBmpBuf + lineByte * i + j;
Num[*(lpBuf)] += 1;
}
start=clock();
HuffmanCode();
finish=clock();
total_time=(finish-start);
printf("识别一张耗时: %d毫秒",total_time);
char writePath[100];
strcpy(writePath,str);
strcat(writePath,"_Huffman.bhd");
saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);
strcpy(writePath,str);
strcat(writePath,"_Huffman.bpt");
saveInfo(writePath,lineByte);
printf("\n编码完成!编码信息保存在 %s_Huffman 文件中\n\n",str);
}
else
{
printf("本程序只支持256色BMP编码!\n");
}
delete []pBmpBuf;
if(biBitCount==8)
delete []pColorTable;
}
printf("\n-----------------------------------------------\n\n\n");
}
else if(ord == 2)
{
printf("\n---Huffman编码BMP文件解码---\n");
printf("\n请输入要解码文件名称:");
scanf("%s",str);
HuffmanCodeInit();
if(readHuffman(str))
{
HuffmanDecode();
char writePath[100];
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");
}
else if(ord == 3)
break;
}
return 0;
}