直方图修正和彩色变换.docx

上传人:b****9 文档编号:26387969 上传时间:2023-06-18 格式:DOCX 页数:47 大小:268.64KB
下载 相关 举报
直方图修正和彩色变换.docx_第1页
第1页 / 共47页
直方图修正和彩色变换.docx_第2页
第2页 / 共47页
直方图修正和彩色变换.docx_第3页
第3页 / 共47页
直方图修正和彩色变换.docx_第4页
第4页 / 共47页
直方图修正和彩色变换.docx_第5页
第5页 / 共47页
点击查看更多>>
下载资源
资源描述

直方图修正和彩色变换.docx

《直方图修正和彩色变换.docx》由会员分享,可在线阅读,更多相关《直方图修正和彩色变换.docx(47页珍藏版)》请在冰豆网上搜索。

直方图修正和彩色变换.docx

直方图修正和彩色变换

第5章直方图修正和彩色变换

这一章,我们主要和调色板打交道。

先从最简单的反色讲起。

5.1反色

反色(invert)就是形成底片效果。

例如,图5.2为图5.1反色后的结果。

图5.1    原图

图5.2    图5.1反色后的结果

反色有时是很有用的,比如,图5.1中黑色区域占绝大多数,这样打印起来很费墨,我们可以先进行反色处理后再打印。

反色的实际含义是将R、G、B值反转。

若颜色的量化级别是256,则新图的R、G、B值为255减去原图的R、G、B值。

这里针对的是所有图,包括真彩图、带调色板的彩色图(又称为伪彩色图)、和灰度图。

针对不同种类有不同的处理。

先看看真彩图。

我们知道真彩图不带调色板,每个象素用3个字节,表示R、G、B三个分量。

所以处理很简单,把反转后的R、G、B值写入新图即可。

再来看看带调色板的彩色图,我们知道位图中的数据只是对应调色板中的一个索引值,我们只需要将调色板中的颜色反转,形成新调色板,而位图数据不用动,就能够实现反转。

灰度图是一种特殊的伪彩色图,只不过调色板中的R、G、B值都是一样的而已。

所以反转的处理和上面讲的一样。

这里,我想澄清一个概念。

过去我们讲二值图时,一直都说成黑白图。

二值位图一定是黑白的吗?

答案是不一定。

我们安装Windows95时看到的那幅setup.bmp是由蓝色和黑色组成的,但它实际上是二值图。

原来,它的调色板中的两种颜色是黑与蓝,而不是黑与白。

所以说二值图也可以是彩色的,只不过一般情况下是黑白图而已。

下面的程序实现了反色,注意其中真彩图和调色板位图处理时的差别。

BOOLInvert(HWNDhWnd)

{

      DWORD                           OffBits,BufSize;

LPBITMAPINFOHEADER   lpImgData;

      LPSTR                 lpPtr;

      HLOCAL                 hTempImgData;

      LPBITMAPINFOHEADER   lpTempImgData;

      LPSTR                 lpTempPtr;

      HDC                   hDc;

      HFILE                  hf;

      LONG                  x,y;

   LOGPALETTE           *pPal;

   HPALETTE              hPrevPalette=NULL;

      HLOCAL                 hPal;

      DWORD                i;

      unsignedchar            Red,Green,Blue;

      OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);

      BufSize=OffBits+bi.biHeight*LineBytes;//新开缓冲区的大小

      if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)

{

MessageBox(hWnd,"Errorallocmemory!

","ErrorMessage",MB_OK|

MB_ICONEXCLAMATION);

returnFALSE;

}

lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);   

      lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);

      //拷贝头信息

memcpy(lpTempImgData,lpImgData,BufSize);

      hDc=GetDC(hWnd);

      if(NumColors!

=0){//NumColors不为0说明是带调色板的

lpPtr=(char*)lpImgData+sizeof(BITMAPINFOHEADER);

//指向原图数据

lpTempPtr=(char*)lpTempImgData+sizeof(BITMAPINFOHEADER);

//指向新图数据

//为新调色板分配内存

hPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+

NumColors*sizeof(PALETTEENTRY));

pPal=(LOGPALETTE*)LocalLock(hPal);

pPal->palNumEntries=(WORD)NumColors;

pPal->palVersion   =0x300;

for(i=0;i

      Blue=(unsignedchar)(*lpPtr++);

      Green=(unsignedchar)(*lpPtr++);

      Red=(unsignedchar)(*lpPtr++);

      lpPtr++;

      //反转调色板中的颜色,存入新的调色板

      pPal->palPalEntry[i].peRed=(BYTE)(255-Red);

pPal->palPalEntry[i].peGreen=(BYTE)(255-Green);

      pPal->palPalEntry[i].peBlue=(BYTE)(255-Blue);

      pPal->palPalEntry[i].peFlags=0;

      *(lpTempPtr++)=(unsignedchar)(255-Blue);

      *(lpTempPtr++)=(unsignedchar)(255-Green);

      *(lpTempPtr++)=(unsignedchar)(255-Red);

      *(lpTempPtr++)=0;

}

if(hPalette!

=NULL)                    

      DeleteObject(hPalette);

hPalette=CreatePalette(pPal);//产生新的调色板

LocalUnlock(hPal);

LocalFree(hPal);

if(hPalette){

      hPrevPalette=SelectPalette(hDc,hPalette,FALSE);

      RealizePalette(hDc);

}

      }

      else{//不带调色板,说明是真彩色图

             for(y=0;y

                    lpPtr=(char*)lpImgData+(BufSize-LineBytes-y*LineBytes);

                    lpTempPtr=(char*)lpTempImgData+(BufSize-LineBytes-y*LineBytes);

                    for(x=0;x

                           Blue=(unsignedchar)(*lpPtr++);

                           Green=(unsignedchar)(*lpPtr++);

                           Red=(unsignedchar)(*lpPtr++);

                           //反转位图数据中的颜色,存入新的位图数据中

                           *(lpTempPtr++)=(unsignedchar)(255-Blue);

                           *(lpTempPtr++)=(unsignedchar)(255-Green);

                           *(lpTempPtr++)=(unsignedchar)(255-Red);

                    }

             }

      }

if(hBitmap!

=NULL)

         DeleteObject(hBitmap);

hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData,

(LONG)CBM_INIT,

                                               (LPSTR)lpTempImgData+

sizeof(BITMAPINFOHEADER)+

         NumColors*sizeof(RGBQUAD),

                                          (LPBITMAPINFO)lpTempImgData,

DIB_RGB_COLORS);

      if(hPalette&&hPrevPalette){

             SelectPalette(hDc,hPrevPalette,FALSE);

             RealizePalette(hDc);

      }

hf=_lcreat("c:

\\invert.bmp",0);

      _lwrite(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));

      _lwrite(hf,(LPSTR)lpTempImgData,BufSize);

      _lclose(hf);

      //释放内存和资源

     ReleaseDC(hWnd,hDc);

      LocalUnlock(hTempImgData);

      LocalFree(hTempImgData);

      GlobalUnlock(hImgData);

      returnTRUE;

}

5.2彩色图转灰度图

第2章中提到了YUV的颜色表示方法,在这种表示方法中,Y分量的物理含义就是亮度,它含了灰度图(grayscale)的所有信息,只用Y分量就完全能够表示出一幅灰度图来。

YUV和RGB之间有着如下的对应关系:

我们利用上式,根据R、G、B的值求出Y值后,将R、G、B值都赋值成Y,就能表示出灰度图来,这就是彩色图转灰度图的原理。

先看看真彩图。

我们知道真彩图不带调色板,每个象素用3个字节,表示R、G、B三个分量。

所以处理很简单,根据R、G、B的值求出Y值后,将R、G、B值都赋值成Y,写入新图即可。

再来看看带调色板的彩色图,我们知道位图中的数据只是对应调色板中的一个索引值,我们只需要将调色板中的彩色变成灰度,形成新调色板,而位图数据不用动,就可以了。

下面的程序实现了彩色图到灰度图的转换,注意其中真彩图和调色板位图处理时的差别。

BOOLColortoGrayScale(HWNDhWnd)

{

DWORD                           SrcOffBits,SrcBufSize,DstBufSize,DstLineBytes;

LPBITMAPINFOHEADER   lpImgData;

      LPSTR                 lpPtr;

      HLOCAL                 hTempImgData;

      LPBITMAPINFOHEADER   lpTempImgData;

      LPSTR                 lpTempPtr;

      HDC                   hDc;

      HFILE                 hf;

      LONG                 x,y;

      BITMAPFILEHEADER       DstBf;

      BITMAPINFOHEADER      DstBi;

LOGPALETTE          *pPal;

HPALETTE                              hPrevPalette;

      HLOCAL                           hPal;

      DWORD                      NewNumColors;

      WORD                                     NewBitCount;

      float                    Y;

      DWORD               i;

      unsignedchar           Red,Green,Blue,Gray;

      NewNumColors=NumColors;//NewNumColors为新图的颜色数

      NewBitCount=bi.biBitCount; //NewBitCount为新图的颜色位数

      if(NumColors==0)//真彩图

{

             NewNumColors=256;

             NewBitCount=8;

      }

//由于颜色位数有可能发生了改变,所以要重新计算每行占用的字节数以及

//新图的缓冲区大小

      DstLineBytes=(DWORD)WIDTHBYTES(bi.biWidth*NewBitCount);

      DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+NewNumColors*

sizeof(RGBQUAD)+(DWORD)DstLineBytes*bi.biHeight);

      //DstBf和DstBi为新的BITMAPFILEHEADER和BITMAPINFOHEADER

      //拷贝原来的头信息

      memcpy((char*)&DstBf,(char*)&bf,sizeof(BITMAPFILEHEADER));

      memcpy((char*)&DstBi,(char*)&bi,sizeof(BITMAPINFOHEADER));

      //做必要的改变

      DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER);

      DstBf.bfOffBits=(DWORD)(NewNumColors*sizeof(RGBQUAD)+

sizeof(BITMAPFILEHEADER)+

sizeof(BITMAPINFOHEADER));

      DstBi.biClrUsed=0;

      DstBi.biBitCount=NewBitCount;

      //原图的缓冲区的大小

      SrcOffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);

SrcBufSize=SrcOffBits+bi.biHeight*LineBytes;

      if((hTempImgData=LocalAlloc(LHND,DstBufSize))==NULL)

{

MessageBox(hWnd,"Errorallocmemory!

","ErrorMessage",MB_OK|

MB_ICONEXCLAMATION);

returnFALSE;

   }

   lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);   

      lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);

//拷贝头信息和位图数据

      memcpy(lpTempImgData,lpImgData,DstBufSize);

      //用新的BITMAPINFOHEADER替换原来的头信息

      memcpy(lpTempImgData,(char*)&DstBi,sizeof(BITMAPINFOHEADER));

      //lpPtr指向原图的数据

      lpPtr=(char*)lpImgData+sizeof(BITMAPINFOHEADER);

      //lpTempPtr指向新图的数据

      lpTempPtr=(char*)lpTempImgData+sizeof(BITMAPINFOHEADER);

//为新的调色板分配内存

hPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+NewNumColors

*sizeof(PALETTEENTRY));

pPal=(LOGPALETTE*)LocalLock(hPal);

pPal->palNumEntries=(WORD)NewNumColors;

      pPal->palVersion   =0x300;

      if(NumColors==0)//真彩色

             for(i=0;i<256;i++){//灰度从(0,0,0)到(255,255,255)

               pPal->palPalEntry[i].peRed=(BYTE)i;

                   pPal->palPalEntry[i].peGreen=(BYTE)i;

                    pPal->palPalEntry[i].peBlue=(BYTE)i;

                    pPal->palPalEntry[i].peFlags=(BYTE)0;

                    *(lpTempPtr++)=(unsignedchar)i;

                    *(lpTempPtr++)=(unsignedchar)i;

                    *(lpTempPtr++)=(unsignedchar)i;

                    *(lpTempPtr++)=0;

             }

      else

             for(i=0;i

                    Blue=(unsignedchar)(*lpPtr++);

                    Green=(unsignedchar)(*lpPtr++);

                    Red=(unsignedchar)(*lpPtr++);

                    Y=(float)(Red*0.299+Green*0.587+Blue*0.114);

                    Gray=(BYTE)Y;

                    lpPtr++;

                    //从原来的调色板中的颜色计算得到Y值,写入新的调色板

               pPal->palPalEntry[i].peRed=Gray;

                    pPal->palPalEntry[i].peGreen=Gray;

                    pPal->palPalEntry[i].peBlue=Gray;

                    pPal->palPalEntry[i].peFlags=0;

                    *(lpTempPtr++)=(unsignedchar)Gray;

                    *(lpTempPtr++)=(unsignedchar)Gray;

                    *(lpTempPtr++)=(unsignedchar)Gray;

                    *(lpTempPtr++)=0;

             }

      if(hPalette!

=NULL)                    

       DeleteObject(hPalette);

//生成新的逻辑调色板

      hPalette=CreatePalette(pPal);

      LocalUnlock(hPal);

      LocalFree(hPal);

      hDc=GetDC(hWnd);

      if(hPalette){

        hPrevPalette=SelectPalette(hDc,hPalette,FALSE);

             RealizePalette(hDc);

      }

      if(NumColors==0)//真彩色图才需要处理位图数据

             for(y=0;y

                    lpPtr=(char*)lpImgData+(SrcBufSize-LineBytes-y*LineBytes);

                    lpTempPtr=(char*)lpTempImgData+

(DstBufSize-DstLineBytes-y*DstLineBytes);

                    for(x=0;x

                           Blue=(unsignedchar)(*lpPtr++);

                     

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

当前位置:首页 > 党团工作 > 入党转正申请

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

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