?? hdib.cpp
字號:
// 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_BmpInfo=0;
m_Quad=0;
m_hPal=0;
BmpMarker=('M'<<8)|'B';
Width=0;
Height=0;
}
CDib::~CDib()
{
Free();
}
//釋放所有動態(tài)分配的內(nèi)存:
void CDib::Free()
{
if(m_Buffer)
{
delete [] m_Buffer;
m_Buffer=0;
}
if(m_BmpInfo)
{
delete [] m_BmpInfo;
m_BmpInfo=0;
}
if(m_Quad)
{
delete [] m_Quad;
m_Quad=0;
}
}
//從文件中讀取位圖:
BOOL CDib::LoadBmp(LPCTSTR fn)
{
if(fn=="")
{
return FALSE;
}
Free();
//打開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);
m_BmpInfo=(LPBITMAPINFO) new BYTE[bmpinfosz];
files.read((char *)m_BmpInfo,m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER));
//計(jì)算位圖的相關(guān)數(shù)據(jù)信息:
CalBmpData();
//只支持8位以上的位圖:
if(BPP<8||BPP>32)
{
Free();
return FALSE;
}
//讀入位圖數(shù)據(jù):
m_Buffer=new BYTE[BufferSize];
files.read((char *)m_Buffer,BufferSize);
if(m_BmpInfo->bmiHeader.biCompression!=BI_RGB)
{
Free();
return FALSE;
}
if(!CreatePalette())
{
Free();
return FALSE;
}
m_BmpLoaded=TRUE;
return TRUE;
}
//將內(nèi)存中的位圖存入文件:
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=位圖數(shù)據(jù)的大小:
m_BmpInfo->bmiHeader.biSizeImage=BufferSize;
//2. 填充bmpfh結(jié)構(gòu);
BITMAPFILEHEADER bmpfh;
memset(&bmpfh,0,sizeof(BITMAPFILEHEADER));
bmpfh.bfType=BmpMarker;
//bmpfh.bfSize=BITMAPFILEHEADER+BITMAPINFO+調(diào)色板+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). 寫入位圖數(shù)據(jù):
sz=fwrite(m_Buffer,1,BufferSize,fp);
if(sz!=BufferSize)
{
fclose(fp);
return FALSE;
}
fclose(fp);
return TRUE;
}
//獲取位圖內(nèi)存地址:
BYTE * CDib::GetBuffer()
{
return m_Buffer;
}
//根據(jù)像素在位圖中的位置求像素在內(nèi)存中的地址:
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. 計(jì)算基本參數(shù):
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的數(shù)目;
bufsize=bpl*h;//位圖數(shù)據(jù)區(qū)大小;
//2. 填寫位圖區(qū):
BYTE * pos,* bufpos;
pos=FindPos(xt,yt);//找到(xt,yt)像素在內(nèi)存中的位置;
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. 填寫位圖結(jié)構(gòu):
BITMAPFILEHEADER fh;
BITMAPINFO info;
memset(&fh ,0,sizeof(BITMAPFILEHEADER));
memset(&info,0,sizeof(BITMAPINFO));
//1. 填充BITMAPINFO結(jié)構(gòu):
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結(jié)構(gòu);
fh.bfType=BmpMarker;
//bmpfh.bfSize=BITMAPFILEHEADER+BITMAPINFO+調(diào)色板+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). 寫入位圖數(shù)據(jù):
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;
//位圖每一行占據(jù)的字節(jié)數(shù):
Bpl=(Width*(BPP/8)+3)&~3;
//位圖數(shù)據(jù)區(qū)尺寸(字節(jié)):
BufferSize=Bpl*Height;
//為m_Quad分配內(nèi)存:
//如果色彩數(shù)目大于8 則返回:
if(m_BmpInfo->bmiHeader.biBitCount>=16||
m_BmpInfo->bmiHeader.biBitCount<8)
{
NumberOfColors=0;
return;
}
if(m_BmpInfo->bmiHeader.biClrUsed==0)
{
NumberOfColors=256;
}
else
{
NumberOfColors=m_BmpInfo->bmiHeader.biClrUsed;
}
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);
}
DWORD CDib::PaletteSize()
{
if (m_BmpInfo==0)
{
return 0;
}
return (DWORD)NumberOfColors*sizeof(RGBQUAD);
}
BOOL CDib::CreatePalette()
{
if (m_BmpInfo==0)
{
return FALSE;
}
if(BPP>=16)
{
return TRUE;
}
DWORD i;
LPLOGPALETTE lpPal = (LPLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*NumberOfColors];
if (lpPal == 0)
{
return FALSE;
}
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;
}
if (m_hPal)
{
::DeleteObject((HGDIOBJ)m_hPal);
}
m_hPal=::CreatePalette(lpPal);
if(!m_hPal)
{
return FALSE;
}
delete [] lpPal;
return TRUE;
}
BOOL CDib::Draw(HDC hDC, LPRECT rcDest, LPRECT rcSrc)
{
if (!m_BmpLoaded)
{
return FALSE;
}
HPALETTE hOldPal = 0;
if (m_hPal!=0)
{
hOldPal = ::SelectPalette(hDC,m_hPal,TRUE);
}
::SetStretchBltMode(hDC, COLORONCOLOR);
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
}
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;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -