图像的霍夫曼编码.docx

上传人:b****7 文档编号:9845246 上传时间:2023-02-07 格式:DOCX 页数:11 大小:201.86KB
下载 相关 举报
图像的霍夫曼编码.docx_第1页
第1页 / 共11页
图像的霍夫曼编码.docx_第2页
第2页 / 共11页
图像的霍夫曼编码.docx_第3页
第3页 / 共11页
图像的霍夫曼编码.docx_第4页
第4页 / 共11页
图像的霍夫曼编码.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

图像的霍夫曼编码.docx

《图像的霍夫曼编码.docx》由会员分享,可在线阅读,更多相关《图像的霍夫曼编码.docx(11页珍藏版)》请在冰豆网上搜索。

图像的霍夫曼编码.docx

图像的霍夫曼编码

实验六图像的霍夫曼编码

一、实验目的:

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

}

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

当前位置:首页 > 高等教育 > 文学

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

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