#include "CDib.h"
//建立空白DIB
CDib::CDib(int Width,int Height,int BitsPerPixel)
:DibBits(NULL),DibInfo(NULL)
{
//调用InitDibInfo()函数填充BITMAPINFO结构
InitDibInfo(BitsPerPixel,Width,Height);
DibBits=(void *)new char[GetImageBodySize()];
}
//读入文件
CDib::CDib(char *bmpfile):DibBits(NULL),DibInfo(NULL)
{
CFile fp(bmpfile,CFile::modeRead|CFile::typeBinary);
DoReadFile(fp);
fp.Close();
}
CDib::CDib(CFile &file):DibBits(NULL),DibInfo(NULL)
{
DoReadFile(file);
}
//由DDB转换
CDib::CDib(CBitmap &ddb,CPalette *palette)
:DibBits(NULL),DibInfo(NULL)
{
BITMAP ddbinfo;
ddb.GetBitmap(&ddbinfo);
InitDibInfo(ddbinfo.bmPlanes*ddbinfo.bmBitsPixel,
ddbinfo.bmWidth,ddbinfo.bmHeight);
DibBits=(void *)new char[GetImageBodySize()];
if(palette) CopyPalette(*palette);
//产生桌面窗口的DC
CWnd DesktopWnd;
DesktopWnd.Attach(::GetDesktopWindow());
CWindowDC desktopDC(&DesktopWnd);
::GetDIBits(desktopDC.m_hDC,
HBITMAP(ddb),
0,
ddbinfo.bmHeight,
LPVOID(DibBits),
DibInfo,
DIB_RGB_COLORS);
DesktopWnd.Detach();
}
CDib::~CDib()
{
delete[] DibInfo;
delete[] DibBits;
}
//取得DIB相关信息
//通过参考BITMAPINFO、BIPMAPINFOHEADER、RGBQUAD的数据结构,返回相应的值
int CDib::GetBitsPerPixel()
{
return (!DibInfo)?0:DibInfo->bmiHeader.biBitCount;
}
void *CDib::GetBits()
{
return DibBits;
}
DWORD CDib::Width()
{
return DibInfo->bmiHeader.biWidth;
}
DWORD CDib::Height()
{
return DibInfo->bmiHeader.biHeight;
}
long CDib::GetImageBodySize()
{
return BytesPerLine()*DibInfo->bmiHeader.biHeight;
}
DWORD CDib::BytesPerLine()
{
DWORD bytes_per_line;
bytes_per_line=(DibInfo->bmiHeader.biWidth*
GetBitsPerPixel()+7)/8;
return bytes_per_line;
}
BOOL CDib::GetDimension(CSize &size)
{
if(!DibInfo) return FALSE;
size.cx=DibInfo->bmiHeader.biWidth;
size.cy=DibInfo->bmiHeader.biHeight;
return TRUE;
}
//取得调色板的大小
int CDib::GetPaletteCount()
{
int PaletteSize=0;
if(!DibInfo) return 0;
switch(DibInfo->bmiHeader.biBitCount)
{
case 1:
PaletteSize=2;
break;
case 4:
PaletteSize=16;
break;
case 8:
PaletteSize=256;
break;
}
return PaletteSize;
}
//取得DIB的调色板
CPalette *CDib::GetPalette()
{
int i;
CPalette *palette;
LOGPALETTE *log;
if(!GetPaletteCount()) return NULL;
//分配DIB的调色板结构的大小
log=(LOGPALETTE *)new char[sizeof(WORD)*2+
sizeof(PALETTEENTRY)*GetPaletteCount()];
log->palVersion=0x300;
log->palNumEntries=WORD(GetPaletteCount());
for(i=0;i<log->palNumEntries;i++)
{
log->palPalEntry[i].peRed=DibInfo->bmiColors[i].rgbRed;
log->palPalEntry[i].peGreen=DibInfo->bmiColors[i].rgbGreen;
log->palPalEntry[i].peBlue=DibInfo->bmiColors[i].rgbBlue;
log->palPalEntry[i].peFlags=NULL;
}
//返回更好使用的CPalette
palette=new CPalette;
palette->CreatePalette(log);
delete[] log;
return palette;
}
BOOL CDib::CopyToDDB(CBitmap &ddb)
{
BOOL ret;
if(!DibInfo) return FALSE;
CWnd DesktopWnd;
DesktopWnd.Attach(::GetDesktopWindow());
CWindowDC dtpDC(&DesktopWnd);
//调用SetDIBits函数将DIB转化成DDB
ret=::SetDIBits(dtpDC.m_hDC,
HBITMAP(ddb),
0,
DibInfo->bmiHeader.biHeight,
DibBits,
DibInfo,
DIB_RGB_COLORS);
DesktopWnd.Detach();
return ret;
}
BOOL CDib::DoSaveFile(char *bmpfile)
{
if(!DibInfo) return FALSE;
CFile fp(bmpfile,CFile::modeCreate|CFile::typeBinary);
DoWriteFile(fp);
fp.Close();
return TRUE;
}
//等尺寸输出
int CDib::SetToDC(CDC &dc,CRect &src,CPoint &dst)
{
if(!DibInfo)return FALSE;
return ::SetDIBitsToDevice(
dc.m_hDC,
dst.x,
dst.y,
src.Width(),
src.Height(),
src.left,
src.top,
0,
DibInfo->bmiHeader.biHeight,
DibBits,
DibInfo,
DIB_RGB_COLORS
);
}
//缩放输出
int CDib::StretchToDC(CDC &dc,CRect &src,CRect &dst,DWORD rop)
{
if(!DibInfo) return FALSE;
return ::StretchDIBits(
dc.m_hDC,
dst.left,
dst.top,
dst.Width(),
dst.Height(),
src.left,
src.top,
src.Width(),
src.Height(),
DibBits,
DibInfo,
DIB_RGB_COLORS,
rop
);
}
//以下几个关键函数的说明请参考文章
BOOL CDib::DoReadFile(CFile &file)
{
BITMAPFILEHEADER bmfileheader;
BITMAPINFOHEADER bmheader;
long size,headpos;
int PaletteSize=0;
int ret,cbHeaderSize;
headpos=file.GetPosition();
ret=file.Read(&bmfileheader,sizeof(BITMAPFILEHEADER));
if((ret!=sizeof(BITMAPFILEHEADER))||(bmfileheader.bfType!=0x4d42))
return FALSE;
ret=file.Read(&bmheader,sizeof(BITMAPINFOHEADER));
if(ret!=sizeof(BITMAPINFOHEADER))
return FALSE;
switch(bmheader.biBitCount)
{
case 1:
PaletteSize=2;
break;
case 4:
PaletteSize=16;
break;
case 8:
PaletteSize=256;
break;
}
cbHeaderSize=sizeof(BITMAPINFOHEADER)+PaletteSize*sizeof(RGBQUAD);
DibInfo=(BITMAPINFO*)new char[cbHeaderSize];
DibInfo->bmiHeader=bmheader;
if(PaletteSize)
{
ret=file.Read(&(DibInfo->bmiColors[0]),PaletteSize*sizeof(RGBQUAD));
if(ret!=int(PaletteSize*sizeof(RGBQUAD)))
{
delete[] DibInfo;
DibInfo=NULL;
return FALSE;
}
}
size=BytesPerLine()*DibInfo->bmiHeader.biHeight;
DibBits=(void*)new char[GetImageBodySize()];
file.Seek(headpos+bmfileheader.bfOffBits,CFile::begin);
ret=file.Read(DibBits,size);
if(ret!=int(size))
{
delete[] DibInfo;
delete[] DibBits;
DibInfo=NULL;
DibBits=NULL;
}
return TRUE;
}
BOOL CDib::DoWriteFile(CFile &file)
{
long size;
int PaletteSize=GetPaletteCount();
BITMAPFILEHEADER bmfileheader;
if(!DibInfo) return FALSE;
size=BytesPerLine()*DibInfo->bmiHeader.biHeight;
bmfileheader.bfType=0x4d42;
bmfileheader.bfReserved1=bmfileheader.bfReserved2=0;
bmfileheader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
+PaletteSize*sizeof(RGBQUAD);
bmfileheader.bfSize=bmfileheader.bfOffBits+size;
file.Write(&bmfileheader,sizeof(BITMAPFILEHEADER));
file.Write(DibInfo,sizeof(BITMAPINFOHEADER)+PaletteSize*sizeof(RGBQUAD));
file.Write(DibBits,size);
return TRUE;
}
void CDib::InitDibInfo(int BitsPerPixel,int w,int h)
{
int i;
int PaletteSize=0,cbHeaderSize;
switch(BitsPerPixel)
{
case 1:
PaletteSize=2;
break;
case 4:
PaletteSize=16;
break;
case 8:
PaletteSize=256;
break;
case 15:
case 16:
BitsPerPixel=16;
break;
}
cbHeaderSize=sizeof(BITMAPINFOHEADER)+PaletteSize*sizeof(RGBQUAD);
if(DibInfo) delete[] DibInfo;
DibInfo=(BITMAPINFO*)new char[cbHeaderSize];
//填写BITMAPINFO表
DibInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
DibInfo->bmiHeader.biWidth=w;
DibInfo->bmiHeader.biHeight=h;
DibInfo->bmiHeader.biPlanes=1;
DibInfo->bmiHeader.biBitCount=short(BitsPerPixel);
DibInfo->bmiHeader.biCompression=BI_RGB;
DibInfo->bmiHeader.biSizeImage=BytesPerLine( )*DibInfo->bmiHeader.biHeight;
DibInfo->bmiHeader.biXPelsPerMeter=
DibInfo->bmiHeader.biYPelsPerMeter=120;
DibInfo->bmiHeader.biClrUsed=PaletteSize;
DibInfo->bmiHeader.biClrImportant=PaletteSize;
if(PaletteSize)
{
for(i=0;i<PaletteSize;i++)
{
DibInfo->bmiColors[i].rgbRed=0;
DibInfo->bmiColors[i].rgbGreen=0;
DibInfo->bmiColors[i].rgbBlue=0;
DibInfo->bmiColors[i].rgbReserved=0;
}
}
}
void CDi