Hdib.cpp
上传用户:cjd055
上传日期:2013-04-01
资源大小:608k
文件大小:13k
- // HDib.cpp: implementation of the CDib class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "HDib.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #endif
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CDib::CDib()
- {
- m_BmpLoaded=FALSE;
- m_Buffer=0;
- m_Buffer1=0;
- m_BmpInfo=0;
- m_Quad=0;
- m_hPal=0;
- BmpMarker=('M'<<8)|'B';
- Width=0;
- Height=0;
- }
- CDib::~CDib()
- {
- Free();
- }
- //释放所有动态分配的内存:
- void CDib::Free()
- {
- if(m_Buffer)
- {
- delete [] m_Buffer;
- m_Buffer=0;
- }
- if(m_Buffer1)
- {
- delete [] m_Buffer1;
- m_Buffer1=0;
- }
- if(m_BmpInfo)
- {
- delete [] m_BmpInfo;
- m_BmpInfo=0;
- }
- if(m_Quad)
- {
- delete [] m_Quad;
- m_Quad=0;
- }
- }
- void CDib::Resize(int sz)
- {
- if(m_Buffer)
- {
- delete [] m_Buffer;
- m_Buffer=0;
- }
- if(m_Buffer1)
- {
- delete [] m_Buffer1;
- m_Buffer1=0;
- }
- m_Buffer=new BYTE[sz];
- m_Buffer1=new BYTE[sz];
- //位图每一行占据的字节数:
- Bpl=(DWORD)WIDTHBYTES(BPP*Width); //一种使bpl为4的整数倍的技巧
- //位图数据区尺寸(字节):
- BufferSize=Bpl*Height;
- }
- //从文件中读取位图:
- BOOL CDib::LoadBmp(LPCTSTR fn)
- {
- int j;
- if(fn=="")
- {
- return FALSE;
- }
- Free();
- arcFileName=fn;
- //打开bmp文件:
- ifstream files(fn,ios::binary|ios::nocreate);
- if(!files.is_open())
- {
- return FALSE;
- }
- //读入BITMAPFILEHEADER:
- files.read((LPSTR)&m_BmpFH, sizeof(BITMAPFILEHEADER));
- //判断是否是bmp文件:
- if (m_BmpFH.bfType != BmpMarker)
- {
- return FALSE;
- }
- //读入BITMAPINFO:
- DWORD bmpinfosz;
- bmpinfosz=m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER)
- +256*sizeof(RGBQUAD); //40+256*4
- m_BmpInfo=(LPBITMAPINFO) new BYTE[bmpinfosz];
- files.read((char *)m_BmpInfo,m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER)); //m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER)=40
- //计算位图的相关数据信息:
- CalBmpData();
- //只支持8位以上的位图:
- if(BPP>32)
- {
- Free();
- return FALSE;
- }
- //读入位图数据:
- m_Buffer=new BYTE[BufferSize];
- m_Buffer1=new BYTE[BufferSize];
- files.read((char *)m_Buffer,BufferSize);
- if(m_BmpInfo->bmiHeader.biCompression!=BI_RGB)
- {
- Free();
- return FALSE;
- }
- if(!CreatePalette())
- {
- Free();
- return FALSE;
- }
- for ( j=0;j<(int)BufferSize;j++)
- {
- *(m_Buffer1+j)=*(m_Buffer+j);
- }
- m_BmpLoaded=TRUE;
- return TRUE;
- }
- //将内存中的位图存入文件:
- BOOL CDib::SaveBmp(LPCTSTR fn)
- {
- if(fn=="")
- {
- return FALSE;
- }
- if(!m_BmpLoaded)
- {
- return FALSE;
- }
- if(m_BmpInfo==0||m_Buffer==0)
- {
- return FALSE;
- }
- //1. 更改m_BmpInfo->bmiHeader.biSizeImage:
- //1. biSizeImage=位图数据的大小:
- m_BmpInfo->bmiHeader.biSizeImage=BufferSize;
- //2. 填充bmpfh结构;
- BITMAPFILEHEADER bmpfh;
- memset(&bmpfh,0,sizeof(BITMAPFILEHEADER));
- bmpfh.bfType=BmpMarker;
- //bmpfh.bfSize=BITMAPFILEHEADER+BITMAPINFO+调色板+BufferSize:
- bmpfh.bfSize=sizeof(BITMAPFILEHEADER)+
- sizeof(BITMAPINFO)+
- (NumberOfColors-1)*sizeof(RGBQUAD)+
- BufferSize;
- bmpfh.bfReserved1=0;
- bmpfh.bfReserved2=0;
- bmpfh.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+
- m_BmpInfo->bmiHeader.biSize+
- PaletteSize();
- //3. 写文件:
- FILE * fp;
- size_t sz;
- if((fp=fopen(fn,"wb"))==NULL)
- {
- return FALSE;
- }
- //1). 写入BITMAPFILEHEADER:
- sz=fwrite((void *)&bmpfh,sizeof(BITMAPFILEHEADER),1,fp);
- if(sz!=1)
- {
- fclose(fp);
- return FALSE;
- }
- //2). 写入BITMAPINFO:
- sz=fwrite((void *)m_BmpInfo,sizeof(BITMAPINFO)+(NumberOfColors-1)*sizeof(RGBQUAD),1,fp);
- if(sz!=1)
- {
- fclose(fp);
- return FALSE;
- }
- //3). 写入位图数据:
- sz=fwrite(m_Buffer,1,BufferSize,fp);
- if(sz!=BufferSize)
- {
- fclose(fp);
- return FALSE;
- }
- fclose(fp);
- return TRUE;
- }
- //获取位图内存地址:
- BYTE * CDib::GetBuffer()
- {
- return m_Buffer;
- }
- //根据像素在位图中的位置求像素在内存中的地址:
- BYTE * CDib::FindPos(DWORD x, DWORD y)
- {
- BYTE * pos;
- if(!m_BmpLoaded)
- {
- return 0;
- }
- pos=m_Buffer+Bpl*(Height-1-y)+x*BPP/8;
- return pos;
- }
- //将位图的子画面存入文件:
- BOOL CDib::PickBitmapToFile(LPCTSTR fn, DWORD xt, DWORD yt,
- DWORD xb, DWORD yb)
- {
- BYTE * buf;
- DWORD w,h,bpl,bufsize,n0;
- if(!m_BmpLoaded)
- {
- return FALSE;
- }
- if(m_BmpInfo==0||m_Buffer==0)
- {
- return FALSE;
- }
- if(fn=="")
- {
- return FALSE;
- }
- //1. 计算基本参数:
- Sort(xt,xb);
- Sort(yt,yb);
- if(xt>Width)
- {
- return FALSE;
- }
- if(yt>Width)
- {
- return FALSE;
- }
- if(xb>Width)
- {
- xb=Width;
- }
- if(yb>Height)
- {
- yb=Height;
- }
- w=xb-xt;//子画面宽度;
- h=yb-yt;//子画面高度;
- bpl=(w*(BPP/8)+3)&~3;//每一行大小;
- n0=bpl-w*BPP/8;//需要在每一行末尾添加的0的数目;
- bufsize=bpl*h;//位图数据区大小;
- //2. 填写位图区:
- BYTE * pos,* bufpos;
- pos=FindPos(xt,yt);//找到(xt,yt)像素在内存中的位置;
- buf=new BYTE[bufsize];
- memset((void *)buf,0,bufsize);
- UINT i;
- bufpos=buf+bpl*(h-1);
- for(i=0;i<h;i++)
- {
- memcpy(bufpos,pos,w*BPP/8);
- bufpos-=bpl;
- pos-=Bpl;
- }
- //3. 填写位图结构:
- BITMAPFILEHEADER fh;
- BITMAPINFO info;
- memset(&fh ,0,sizeof(BITMAPFILEHEADER));
- memset(&info,0,sizeof(BITMAPINFO));
- //1. 填充BITMAPINFO结构:
- info.bmiHeader.biBitCount=(WORD)BPP;
- info.bmiHeader.biClrImportant=m_BmpInfo->bmiHeader.biClrImportant;
- info.bmiHeader.biClrUsed=m_BmpInfo->bmiHeader.biClrUsed;
- info.bmiHeader.biCompression=BI_RGB;
- info.bmiHeader.biHeight=h;
- info.bmiHeader.biPlanes=m_BmpInfo->bmiHeader.biPlanes;
- info.bmiHeader.biSize=m_BmpInfo->bmiHeader.biSize;
- info.bmiHeader.biSizeImage=bufsize;
- info.bmiHeader.biWidth=w;
- info.bmiHeader.biXPelsPerMeter=m_BmpInfo->bmiHeader.biXPelsPerMeter;
- info.bmiHeader.biYPelsPerMeter=m_BmpInfo->bmiHeader.biYPelsPerMeter;
- info.bmiColors[0]=m_BmpInfo->bmiColors[0];
- //2. 填充bmpfh结构;
- fh.bfType=BmpMarker;
- //bmpfh.bfSize=BITMAPFILEHEADER+BITMAPINFO+调色板+BufferSize:
- fh.bfSize=sizeof(BITMAPFILEHEADER)+
- sizeof(BITMAPINFO)+
- (NumberOfColors-1)*sizeof(RGBQUAD)+
- bufsize;
- fh.bfReserved1=0;
- fh.bfReserved2=0;
- fh.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+
- m_BmpInfo->bmiHeader.biSize+
- PaletteSize();
- //4. 写文件:
- FILE * fp;
- if((fp=fopen(fn,"wb"))==NULL)
- {
- return FALSE;
- }
- //1). 写入BITMAPFILEHEADER:
- fwrite((char *)&fh,sizeof(BITMAPFILEHEADER),1,fp);
- //2). 写入BITMAPINFOHEADER部分:
- fwrite((char *)&info.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
- //3). //写入彩色表部分:
- if(BPP<16)
- {
- fwrite((char *)&m_Quad[0],NumberOfColors*sizeof(RGBQUAD),1,fp);
- }
- //4). 写入位图数据:
- fwrite((char *)buf,bufsize,1,fp);
- delete buf;
- fclose(fp);
- return TRUE;
- }
- void CDib::CalBmpData()
- {
- if(m_BmpInfo==0)
- {
- return;
- }
- //1. 位图宽度(像素):
- Width=m_BmpInfo->bmiHeader.biWidth;
- //位图高度(像素):
- Height=m_BmpInfo->bmiHeader.biHeight;
- //位图色彩深度:
- BPP=m_BmpInfo->bmiHeader.biBitCount; //取值可为1,4,8,16,24,32,如取值16,24,32,则彩色表不是必须的
- //位图每一行占据的字节数:
- Bpl=(DWORD)WIDTHBYTES(BPP*Width); //一种使bpl为4的整数倍的技巧
- //位图数据区尺寸(字节):
- BufferSize=Bpl*Height;
- //为m_Quad分配内存:
- //如果色彩数目大于8 则返回:
- if(m_BmpInfo->bmiHeader.biBitCount>=16)
- {
- NumberOfColors=0;
- return;
- }
- if(m_BmpInfo->bmiHeader.biClrUsed!=0)
- {
- NumberOfColors=m_BmpInfo->bmiHeader.biClrUsed;
- }
- else
- {
- switch(BPP){
- case 1:
- NumberOfColors=2;
- break;
- case 4:
- NumberOfColors=16;
- break;
- case 8:
- NumberOfColors=256;
- break;
- default:
- return;
- }
- }
- //读取 logical palette
- m_Quad=new RGBQUAD[NumberOfColors];
- for(DWORD i=0;i<NumberOfColors;i++)
- {
- m_Quad[i]=m_BmpInfo->bmiColors[i];
- }
- }
- void CDib::SetBmpMarker(DWORD b, DWORD m)
- {
- BmpMarker=(WORD)((m<<8)|b); //'m'左移8位 and 'b' 再强制类型转换
- }
- DWORD CDib::PaletteSize()
- {
- if (m_BmpInfo==0)
- {
- return 0;
- }
- return (DWORD)NumberOfColors*sizeof(RGBQUAD);//256*4
- }
- //using bmp file's QUAD to change phisical palette
- BOOL CDib::CreatePalette()
- {
- if (m_BmpInfo==0)
- {
- return FALSE;
- }
- //16位以下的位图均需要 logical palette
- if(BPP>=16)
- {
- return TRUE;
- }
- DWORD i;
- // allocate memory block for 逻辑彩色区logical palette
- LPLOGPALETTE lpPal = (LPLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*NumberOfColors]; //sizeof(PALETTEENTRY)*NumberOfColors=4*256 bytes
- // if not enough memory, clean up and return NULL
- if (lpPal == 0)
- {
- return FALSE;
- }
- // set version and number of palette entries
- lpPal->palVersion = PALVERSION;
- lpPal->palNumEntries = (WORD)NumberOfColors;
- for (i=0;i<NumberOfColors;i++)
- {
- lpPal->palPalEntry[i].peRed = m_Quad[i].rgbRed;
- lpPal->palPalEntry[i].peGreen = m_Quad[i].rgbGreen;
- lpPal->palPalEntry[i].peBlue = m_Quad[i].rgbBlue;
- lpPal->palPalEntry[i].peFlags = 0;
- }
- /* according to bmp file palette table,create the palette and
- get handle to it */
- if (m_hPal)
- {
- ::DeleteObject((HGDIOBJ)m_hPal); //删除老的逻辑调色对象
- }
- m_hPal=::CreatePalette(lpPal); //创建新的逻辑调色对象
- if(!m_hPal)
- {
- return FALSE;
- }
- delete [] lpPal; //作用完即destroy logical Palette
- return TRUE;
- }
- BOOL CDib::Draw(HDC hDC, LPRECT rcDest, LPRECT rcSrc)
- {
- if (!m_BmpLoaded)
- {
- return FALSE;
- }
- HPALETTE hOldPal = 0; // Previous palette
- // Get the DIB's palette, then select it into DC
- if (m_hPal!=0)
- {
- // Select as background since we have
- // already realized in forground if needed
- hOldPal = ::SelectPalette(hDC,m_hPal,TRUE); //selects the specified logical palette into a device context
- }
- /* Make sure to use the stretching mode best for color pictures */
- ::SetStretchBltMode(hDC, COLORONCOLOR);
- /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
- BOOL Ok;
- if ((RECTWIDTH(rcDest) == RECTWIDTH(rcSrc)) &&
- (RECTHEIGHT(rcDest) == RECTHEIGHT(rcSrc)))
- {
- Ok = ::SetDIBitsToDevice(hDC, // hDC
- rcDest->left, // DestX
- rcDest->top, // DestY
- RECTWIDTH(rcDest), // nDestWidth
- RECTHEIGHT(rcDest), // nDestHeight
- rcSrc->left, // SrcX
- Height-rcSrc->top -RECTHEIGHT(rcSrc),// SrcY
- 0, // nStartScan
- (WORD)Height, // nNumScans
- m_Buffer, // lpBits
- m_BmpInfo, // lpBitsInfo
- DIB_RGB_COLORS); // wUsage
- }
- else
- {
- Ok = ::StretchDIBits(hDC, // hDC
- rcDest->left, // DestX
- rcDest->top, // DestY
- RECTWIDTH(rcDest), // nDestWidth
- RECTHEIGHT(rcDest), // nDestHeight
- rcSrc->left, // SrcX
- rcSrc->top, // SrcY
- RECTWIDTH(rcSrc), // wSrcWidth
- RECTHEIGHT(rcSrc), // wSrcHeight
- m_Buffer, // lpBits
- m_BmpInfo, // lpBitsInfo
- DIB_RGB_COLORS, // wUsage
- SRCCOPY); // dwROP
- }
- /* Reselect old palette */
- if (hOldPal != 0)
- {
- ::SelectPalette(hDC, hOldPal, TRUE); //恢复老的调色板
- }
- return Ok;
- }
- void CDib::Sort(DWORD &x0, DWORD &x1)
- {
- DWORD t;
- if(x0>x1)
- {
- t=x1;
- x1=x0;
- x0=t;
- }
- }
- BITMAPINFOHEADER CDib::GetImageInfo(LPCTSTR fn, DWORD &w, DWORD &h)
- {
- BITMAPFILEHEADER bmpfilehdr;
- BITMAPINFOHEADER bmpinfohdr;
- w=0;
- h=0;
- memset(&bmpfilehdr,0,sizeof(BITMAPFILEHEADER)); //初始化内存并得到内存指针;
- memset(&bmpinfohdr,0,sizeof(BITMAPINFOHEADER));
- ifstream file( fn, ios::binary | ios::nocreate ); //打开已存在的且二进制的文件;
- if (!file.is_open())
- {
- return bmpinfohdr;
- }
- file.read( (char*)&bmpfilehdr, sizeof(bmpfilehdr) );
- if (bmpfilehdr.bfType!=(WORD)BmpMarker)
- {
- return bmpinfohdr;
- }
- file.read( (char*)&bmpinfohdr, sizeof(bmpinfohdr) );
- w=bmpinfohdr.biWidth;
- h=bmpinfohdr.biHeight;
- return bmpinfohdr;
- }
- void CDib::restoreimage()
- {
- int j;
- for ( j=0;j<(int)BufferSize;j++)
- {
- *(m_Buffer+j)=*(m_Buffer1+j);
- }
- }
- BOOL CDib::GetBlueImg()
- {
- if (BPP<=8)
- return FALSE;
- int i,j;
- for(i=0;i<(int)Height;i++)
- {
- for ( j=0;j<(int)Bpl-2;j=j+3)
- {
- *(m_Buffer+i*Bpl+j+1)=0;
- *(m_Buffer+i*Bpl+j+2)=0;
- }
- }
- return TRUE;
- }
- BOOL CDib::GetGreenImg()
- {
- if (BPP<=8)
- return FALSE;
- int i,j;
- for(i=0;i<(int)Height;i++)
- {
- for ( j=0;j<(int)Bpl-2;j=j+3)
- {
- *(m_Buffer+i*Bpl+j)=0;
- *(m_Buffer+i*Bpl+j+2)=0;
- }
- }
- return TRUE;
- }
- BOOL CDib::GetRedImg()
- {
- if (BPP<=8)
- return FALSE;
- int i,j;
- for(i=0;i<(int)Height;i++)
- {
- for ( j=0;j<(int)Bpl-2;j=j+3)
- {
- *(m_Buffer+i*Bpl+j)=0;
- *(m_Buffer+i*Bpl+j+1)=0;
- }
- }
- return TRUE;
- }