图像的霍夫曼编码.docx
《图像的霍夫曼编码.docx》由会员分享,可在线阅读,更多相关《图像的霍夫曼编码.docx(11页珍藏版)》请在冰豆网上搜索。
图像的霍夫曼编码
实验六图像的霍夫曼编码
一、实验目的:
1)理解并熟练对图像进行霍夫曼编码的算法;
2)进一步加深对所学数字图像处理内容的认识;
3)能够利用各种软件对算法加以实现。
二、实验内容:
1)对数字图像进行哈弗曼编码
2)对数字图像进行算术编码
3)分析所得到的结果。
三、实验原理
哈夫曼(Huffman)编码是一种常用的压缩编码方法,是Huffman于1952年为压缩文本文件建立的。
它的基本原理是频繁使用的数据用较短的代码代替,较少使用的数据用较长的代码代替,每个数据的代码各不相同。
这些代码都是二进制码,且码的长度是可变的。
具体算法如下:
1)首先统计出每个符号出现的频率,上例S0到S7的出现频率分别为4/14,3/14,2/14,1/14,1/14,1/14,1/14,1/14。
2)从左到右把上述频率按从小到大的顺序排列。
3)每一次选出最小的两个值,作为二叉树的两个叶子节点,将和作为它们的根节点,这两个叶子节点不再参与比较,新的根节点参与比较。
4)重复(3),直到最后得到和为1的根节点。
5)将形成的二叉树的左节点标0,右节点标1。
把从最上面的根节点到最下面的叶子节点途中遇到的0,1序列串起来,就得到了各个符号的编码。
四、实验过程
1)实验流程图
霍夫曼编码示意图如下:
2)实验代码
见实验报告附页。
五、实验结果
1)打开要进行编码的图片,如下图所示:
2)对图片进行霍夫曼编码,得到如下结果:
六、实验总结
1)通过本实验,进一步加深了对霍夫曼编码的实验原理和算法的理解和认识;
2)加强了分析问题和解决问题的能力;
3)熟练了软件的使用能力,提高了利用软件对数字图像进行处理的能力。
附页:
实验代码:
unsignedint PcxBytesPerLine;
BOOLLoadPcxFile(HWNDhWnd,char*PcxFileName)
{
FILE *PCXfp;
PCXHEAD header;
LOGPALETTE *pPal;
HPALETTE hPrevPalette;
HDC hDc;
HLOCAL hPal;
DWORD ImgSize;
DWORD OffBits,BufSize;
LPBITMAPINFOHEADER lpImgData;
DWORD i;
LONG x,y;
int PcxTag;
unsignedchar LineBuffer[6400];
LPSTR lpPtr;
HFILE hfbmp;
if((PCXfp=fopen(PcxFileName,"rb"))==NULL){//文件没有找到
MessageBox(hWnd,"Filec:
\\test.pcxnotfound!
","ErrorMessage",
MB_OK|MB_ICONEXCLAMATION);
returnFALSE;
}
//读出头信息
fread((char*)&header,1,sizeof(PCXHEAD),PCXfp);
if(header.manufacturer!
=0x0a){//不是一个合法的PCX文件
MessageBox(hWnd,"NotavalidPcxfile!
","ErrorMessage",
MB_OK|MB_ICONEXCLAMATION);
fclose(PCXfp);
returnFALSE;
}
//将文件指针指向调色板开始处
fseek(PCXfp,-769L,SEEK_END);
//获取颜色数信息
PcxTag=fgetc(PCXfp)&0xff;
if(PcxTag!
=12){//非256色,返回
MessageBox(hWnd,"Nota256colorsPcxfile!
","ErrorMessage",
MB_OK|MB_ICONEXCLAMATION);
fclose(PCXfp);
returnFALSE;
}
//创建新的BITMAPFILEHEADER和BITMAPINFOHEADER
memset((char*)&bf,0,sizeof(BITMAPFILEHEADER));
memset((char*)&bi,0,sizeof(BITMAPINFOHEADER));
//填写BITMAPINFOHEADER头信息
bi.biSize=sizeof(BITMAPINFOHEADER);
//得到图象的宽和高
bi.biWidth=header.xmax-header.xmin+1;
bi.biHeight=header.ymax-header.ymin+1;
bi.biPlanes=1;
bi.biBitCount=8;
bi.biCompression=BI_RGB;
ImgWidth=bi.biWidth;
ImgHeight=bi.biHeight;
NumColors=256;
LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);
ImgSize=(DWORD)LineBytes*bi.biHeight;
//填写BITMAPFILEHEADER头信息
bf.bfType=0x4d42;
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
NumColors*sizeof(RGBQUAD)+ImgSize;
bf.bfOffBits=(DWORD)(NumColors*sizeof(RGBQUAD)+
sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER));
//为新图分配缓冲区
if((hImgData=GlobalAlloc(GHND,(DWORD)
(sizeof(BITMAPINFOHEADER)+
NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL)
{
MessageBox(hWnd,"Errorallocmemory!
","ErrorMessage",
MB_OK|MB_ICONEXCLAMATION);
fclose(PCXfp);
returnFALSE;
}
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
//拷贝头信息
memcpy(lpImgData,(char*)&bi,sizeof(BITMAPINFOHEADER));
lpPtr=(char*)lpImgData+sizeof(BITMAPINFOHEADER);
//为256色调色板分配内存
hPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+
NumColors*sizeof(PALETTEENTRY));
pPal=(LOGPALETTE*)LocalLock(hPal);
pPal->palNumEntries=256;
pPal->palVersion=0x300;
for(i=0;i<256;i++){
//读取调色板中的RGB值
pPal->palPalEntry[i].peRed=(BYTE)fgetc(PCXfp);
pPal->palPalEntry[i].peGreen=(BYTE)fgetc(PCXfp);
pPal->palPalEntry[i].peBlue=(BYTE)fgetc(PCXfp);
pPal->palPalEntry[i].peFlags=(BYTE)0;
*(lpPtr++)=(unsignedchar)pPal->palPalEntry[i].peBlue;
*(lpPtr++)=(unsignedchar)pPal->palPalEntry[i].peGreen;
*(lpPtr++)=(unsignedchar)pPal->palPalEntry[i].peRed;
*(lpPtr++)=0;
}
//产生新的逻辑调色板
hPalette=CreatePalette(pPal);
LocalUnlock(hPal);
LocalFree(hPal);
hDc=GetDC(hWnd);
if(hPalette){
hPrevPalette=SelectPalette(hDc,hPalette,FALSE);
RealizePalette(hDc);
}
//解码行所占的字节数
PcxBytesPerLine=(unsignedint)header.bytes_per_line;
//将文件指针指向图象数据的开始处
fseek(PCXfp,(LONG)sizeof(PCXHEAD),SEEK_SET);
//缓冲区大小
OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);
//BufSize为缓冲区大小
BufSize=OffBits+bi.biHeight*LineBytes;
for(y=0;y //指向新图中相应的位置
lpPtr=(char*)lpImgData+BufSize-LineBytes-y*LineBytes;
//解码该行,放在数组LineBuffer中
ReadPcxLine(LineBuffer,PCXfp);
for(x=0;x *(lpPtr++)=LineBuffer[x];//将该行存储到位图数据中
}
//创建新的位图
hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData,
(LONG)CBM_INIT,
(LPSTR)lpImgData+
sizeof(BITMAPINFOHEADER)+
NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpImgData,
DIB_RGB_COLORS);
if(hPalette&&hPrevPalette){
SelectPalette(hDc,hPrevPalette,FALSE);
RealizePalette(hDc);
}
hfbmp=_lcreat("c:
\\pcx2bmp.bmp",0);
_lwrite(hfbmp,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));
_lwrite(hfbmp,(LPSTR)lpImgData,BufSize);
_lclose(hfbmp);
fclose(PCXfp);
//释放内存和资源
ReleaseDC(hWnd,hDc);
GlobalUnlock(hImgData);
returnTRUE;
}
//对每一行进行解码,结果存储到指针p指向的内存中
voidReadPcxLine(unsignedchar*p,FILE*fp)
{
unsignedint n=0,i;
char c;
memset(p,0,PcxBytesPerLine);
do{
//读出一个字节
c=fgetc(fp)&0xff;
if((c&0xc0)==0xc0){//是个形成字节
//i为c的低六位
i=c&0x3f;
//下一个字节为实际的图象数据
c=fgetc(fp);
while(i--)p[n++]=c;//填充连续的i个字节到p中
}
elsep[n++]=c;//否则是实际的图象数据,直接填入到p中
}while(n}