📄 dibdc.cpp
字号:
// DIBDC.cpp: implementation of the CDIBDC class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DIBDC.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define HIMETRIC_INCH 2540
#define PIXEL_PER_METER 3780
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CDIBDC, CDC)
VOID CDIBDC::ResetParams()
{
m_hDIBitmap = NULL;
m_Index=NULL;
m_pData=NULL;
}
CDIBDC::CDIBDC()
{
ResetParams();
m_BitmapInfo.bmiHeader.biSize=sizeof(m_BitmapInfo.bmiHeader);
m_BitmapInfo.bmiHeader.biPlanes=1;
m_BitmapInfo.bmiHeader.biCompression=BI_RGB;
m_BitmapInfo.bmiHeader.biSizeImage=0;
m_BitmapInfo.bmiHeader.biXPelsPerMeter=PIXEL_PER_METER;
m_BitmapInfo.bmiHeader.biYPelsPerMeter=PIXEL_PER_METER;
m_BitmapInfo.bmiHeader.biClrUsed=0;
m_BitmapInfo.bmiHeader.biClrImportant=0;
CreateDIB(10, 10, 8);
}
CDIBDC::~CDIBDC()
{
DestroyDIB();
}
BOOL CDIBDC::CreateDIB(LONG width, LONG height, WORD bits)
{
m_BitmapInfo.bmiHeader.biHeight=height;
m_BitmapInfo.bmiHeader.biWidth=width;
m_BitmapInfo.bmiHeader.biBitCount=bits;
if(!ResetDIB())
return FALSE;
if(bits<=8)
{
SetDefaultColors();
}
return TRUE;
}
BOOL CDIBDC::ResetDIB()
{
if(m_hDC == NULL)
{
if(!CreateCompatibleDC(NULL))
return FALSE;
}
m_hDIBitmap=::CreateDIBSection(m_hDC,&m_BitmapInfo,DIB_RGB_COLORS,(void**)&m_pData,NULL,0);
if(m_hDIBitmap == NULL)
return FALSE;
if(m_pData != NULL)
{
if(LockIndex() == NULL)
{
::DeleteObject(m_hDIBitmap);
m_hDIBitmap = NULL;
m_pData = NULL;
m_Index = NULL;
return FALSE;
}
}
::DeleteObject(::SelectObject(m_hDC,m_hDIBitmap));
return TRUE;
}
void CDIBDC::SetColors(int index, BYTE r, BYTE g, BYTE b)
{
if(index>255)
return;
RGBQUAD color;
::GetDIBColorTable(m_hDC, index, 1, &color);
color.rgbRed=r;
color.rgbGreen=g;
color.rgbBlue=b;
::SetDIBColorTable(m_hDC,index,1,&color);
}
INT CDIBDC::GetFreeImage(CFile *pFile)
{
WORD width,height;
pFile->SeekToBegin();
pFile->Read(&width,2);
pFile->Read(&height,2);
if(DWORD(width)*height+4!=pFile->GetLength())
return FALSE;
CreateDIB(width,height,8);
SetDefaultColors(TRUE);
for(WORD i=0;i<height;i++)
{
pFile->Read(&(m_pData[(height-i-1)*RowBytes()]),width);
}
return TRUE;
}
void CDIBDC::SaveFreeImage(CFile *pFile, BOOL IsGray)
{
if(Bits()!=8 || IsGray==FALSE)
{
CDIBDC tempDC;
tempDC.CreateDIB(Width(),abs(Height()),8);
tempDC.SetDefaultColors(TRUE);
this->Paste(&tempDC,0,0);
*this=tempDC;
}
pFile->SeekToBegin();
WORD width=WORD(Width());
WORD height=WORD(Height());
pFile->Write(&width,2);
pFile->Write(&height,2);
for(WORD i=0;i<height;i++)
{
pFile->Write(&(m_pData[(height-i-1)*RowBytes()]),width);
}
}
BOOL CDIBDC::GetBitmap(CFile * pFile)
{
char bm[3];
DWORD value;
DWORD lHeadLength;
DWORD TotalSize;
pFile->SeekToBegin();
pFile->Read(bm,2);
if(bm[0]!='B' || bm[1]!='M')
return FALSE;
pFile->Read(&TotalSize,4);
if(pFile->GetLength()<TotalSize)
return FALSE;
pFile->Read(&value,4);
pFile->Read(&lHeadLength,4);
INT bihSize;
pFile->Read(&bihSize,4);
ULONGLONG current=pFile->Seek(-4l,CFile::current);
if(m_BitmapInfo.bmiHeader.biSize+current>pFile->GetLength())
return FALSE;
if(bihSize == sizeof(BITMAPINFOHEADER))
pFile->Read(&m_BitmapInfo.bmiHeader,m_BitmapInfo.bmiHeader.biSize);
else
return FALSE;
ResetDIB();
LONG ColorsSize=lHeadLength-m_BitmapInfo.bmiHeader.biSize-0xE;
if(ColorsSize>0)
{
RGBQUAD colors[256];
pFile->Read(colors,ColorsSize);
SetColorTable(colors);
}
pFile->Read(m_pData,ImageSize());
return TRUE;
}
void CDIBDC::SaveBitmap(CFile * pFile)
{
char bm[3]="BM";
LONG value=0;
LONG lHeadLength=0xE+m_BitmapInfo.bmiHeader.biSize;
if(Bits()<=8)
lHeadLength+=4*(1<<Bits());
LONG TotalSize=ImageSize()+lHeadLength;
BITMAPINFOHEADER bmiHeader=m_BitmapInfo.bmiHeader;
if(Height()<0)
bmiHeader.biHeight=-Height();
pFile->SeekToBegin();
pFile->Write(bm,2);
pFile->Write(&TotalSize,4);
pFile->Write(&value,4);
pFile->Write(&lHeadLength,4);
pFile->Write(&bmiHeader,bmiHeader.biSize);
if(Bits()<=8)
{
RGBQUAD ColorTable[256];
GetColorTable(ColorTable);
pFile->Write(ColorTable,4*(1<<Bits()));
}
if(Height()>0)
{
pFile->Write(m_pData,ImageSize());
}
else
{
for(int i=-Height()-1;i>=0;i--)
{
pFile->Write(m_Index[i], RowBytes());
}
}
}
void CDIBDC::SetDefaultColors(BOOL IsGray)
{
if(!IsValid())
return;
RGBQUAD ColorTable[256];
switch(Bits())
{
case 1:
ColorTable[0].rgbRed=0;
ColorTable[0].rgbGreen=0;
ColorTable[0].rgbBlue=0;
ColorTable[0].rgbReserved=0;
ColorTable[1].rgbRed=0xff;
ColorTable[1].rgbGreen=0xff;
ColorTable[1].rgbBlue=0xff;
ColorTable[1].rgbReserved=0;
SetColorTable(ColorTable);
break;
case 4:
if(IsGray)
{
for(int i=0;i<16;i++)
{
ColorTable[i].rgbRed=i<<4;
ColorTable[i].rgbGreen=i<<4;
ColorTable[i].rgbBlue=i<<4;
ColorTable[i].rgbReserved=0;
}
}
else
{
for(int i=0;i<16;i++)
{
int r,g,b,l;
if(i&8)l=0x7f;
else l=0;
if(i&1)r=0x80;
else r=0;
if(i&2)g=0x80;
else g=0;
if(i&4)b=0x80;
else b=0;
ColorTable[i].rgbRed=r+l;
ColorTable[i].rgbGreen=g+l;
ColorTable[i].rgbBlue=b+l;
ColorTable[i].rgbReserved=0;
}
}
SetColorTable(ColorTable);
break;
case 8:
if(IsGray)
{
for(int i=0;i<256;i++)
{
ColorTable[i].rgbRed=i;
ColorTable[i].rgbGreen=i;
ColorTable[i].rgbBlue=i;
ColorTable[i].rgbReserved=0;
}
}
else
{
BYTE r=0,g=0,b=0xc0;
for(int i=0;i<256;i++)
{
b+=0x40;
if(b>0x80)b=0xff;
if(b==0x3f)
{
b=0;
g+=0x20;
if(g>0xc0)g=0xff;
if(g==0x1f)
{
g=0;
r+=0x20;
if(r>0xc0)r=0xff;
}
}
ColorTable[i].rgbRed=r;
ColorTable[i].rgbGreen=g;
ColorTable[i].rgbBlue=b;
ColorTable[i].rgbReserved=0;
}
}
SetColorTable(ColorTable);
break;
default:break;
}
}
void CDIBDC::Paste(CDC* pDC,
int XDest, int YDest,
int nDestWidth, int nDestHeight,
int XSrc, int YSrc,
int nSrcWidth, int nSrcHeight,
DWORD dwRop)
{
ASSERT(pDC != NULL && IsValid());
pDC->StretchBlt(
XDest,YDest,nDestWidth,nDestHeight,
this,
XSrc,YSrc,nSrcWidth,nSrcHeight,
dwRop);
}
void CDIBDC::Paste(CDC* pDC,
int XDest, int YDest,
int nWidth, int nHeight,
int XSrc, int YSrc,
DWORD dwRop)
{
ASSERT(pDC != NULL && IsValid());
pDC->StretchBlt(
XDest,YDest,nWidth,nHeight,
this,
XSrc,YSrc,nWidth,nHeight,
dwRop);
}
void CDIBDC::Paste(CDC* pDC,
int XDest, int YDest,
int nDestWidth, int nDestHeight,
DWORD dwRop)
{
ASSERT(pDC != NULL && IsValid());
pDC->StretchBlt(
XDest,YDest,nDestWidth,nDestHeight,
this,
0,0,Width(),abs(Height()),
dwRop);
}
void CDIBDC::Paste(CDC* pDC,
int XDest, int YDest,
DWORD dwRop)
{
ASSERT(pDC != NULL && IsValid());
pDC->StretchBlt(
XDest,YDest,Width(),abs(Height()),
this,
0,0,Width(),abs(Height()),
dwRop);
}
BOOL CDIBDC::CreateCompatibleDC(CDC * pDC)
{
DeleteDC();
CDC::CreateCompatibleDC(pDC);
if(m_hDIBitmap != NULL)
{
if(m_hDC != NULL)
::SelectObject(m_hDC,m_hDIBitmap);
else
DestroyDIB();
}
return m_hDC != NULL;
}
BOOL CDIBDC::ClipboardCopy()
{
BOOL bHaveCopied=FALSE;
if(OpenClipboard(AfxGetMainWnd()->m_hWnd))
{
if(EmptyClipboard())
{
HGLOBAL hDIB=GlobalAlloc(GMEM_MOVEABLE,DIBSize());
PVOID pDIB=GlobalLock(hDIB);
SaveToMem(pDIB);
SetClipboardData(CF_DIB,hDIB);
GlobalUnlock(hDIB);
bHaveCopied=TRUE;
}
CloseClipboard();
}
return bHaveCopied;
}
BOOL CDIBDC::ClipboardPaste()
{
BOOL bHavePasted=FALSE;
if(OpenClipboard(AfxGetMainWnd()->m_hWnd))
{
if(IsClipboardFormatAvailable(CF_DIB))
{
HGLOBAL hDIB=GetClipboardData(CF_DIB);
PVOID pDIB=GlobalLock(hDIB);
bHavePasted = LoadFromMem(pDIB);
GlobalUnlock(hDIB);
}
CloseClipboard();
}
return bHavePasted;
}
BOOL CDIBDC::ClipboardAvailable()
{
BOOL bIsAvailable=FALSE;
if(OpenClipboard(AfxGetMainWnd()->m_hWnd))
{
if(IsClipboardFormatAvailable(CF_DIB))
{
bIsAvailable=TRUE;
}
CloseClipboard();
}
return bIsAvailable;
}
LONG& CDIBDC::Width()
{
return m_BitmapInfo.bmiHeader.biWidth;
}
LONG& CDIBDC::Height()
{
return m_BitmapInfo.bmiHeader.biHeight;
}
DWORD CDIBDC::ImageSize()
{
return abs(Height())*RowBytes();
}
WORD& CDIBDC::Bits()
{
return m_BitmapInfo.bmiHeader.biBitCount;
}
LONG CDIBDC::RowBytes()
{
return ((Width()*Bits() + 7)/8+3)/4*4;
}
void CDIBDC::SetColorTable(RGBQUAD * pColors)
{
if(Bits()<=8)
::SetDIBColorTable(m_hDC,0,1<<Bits(),pColors);
}
BOOL CDIBDC::GetColorTable(RGBQUAD *pColors)
{
if(IsValid() && Bits() <= 8)
{
::GetDIBColorTable(m_hDC, 0, 1<<Bits(), pColors);
return TRUE;
}
else
return FALSE;
}
BOOL CDIBDC::ResizeDIB(LONG width, LONG height)
{
if(Width()==width && Height()==height)
return TRUE;
LONG tempWidth=Width();
LONG tempHeight=Height();
Height()=height;
Width()=width;
m_BitmapInfo.bmiHeader.biSizeImage=0;
RGBQUAD ColorTable[256];
GetColorTable(ColorTable);
HBITMAP hDIBitmap=::CreateDIBSection(m_hDC,&m_BitmapInfo,DIB_RGB_COLORS,(PVOID*)&m_pData,NULL,0);
HBITMAP hTempDIB=HBITMAP(::SelectObject(m_hDC,hDIBitmap));
SetColorTable(ColorTable);
LONG minWidth=Width();
if(minWidth>tempWidth)
minWidth=tempWidth;
LONG minHeight=abs(Height());
if(minHeight>abs(tempHeight))
minHeight=abs(tempHeight);
CDC tempDC;
tempDC.CreateCompatibleDC(this);
tempDC.SelectObject(hTempDIB);
this->BitBlt(0,0,minWidth,minHeight,&tempDC,0,0,SRCCOPY);
tempDC.DeleteDC();
::DeleteObject(hTempDIB);
LockIndex();
return TRUE;
}
BOOL CDIBDC::AddDIB(CDIBDC & DIBDC, int x, int y, BOOL IsSuitable)
{
if(x<0 || y<0)
return FALSE;
if(IsSuitable)
{
LONG width=x+DIBDC.Width();
if(Width()>width)
width=Width();
LONG height=y+abs(DIBDC.Height());
if(abs(Height())>height)
height=abs(Height());
ResizeDIB(width,height);
}
BitBlt(x,y,DIBDC.Width(),DIBDC.Height(),&DIBDC,0,0,SRCCOPY);
return TRUE;
}
BOOL CDIBDC::CreateDIB(CDIBDC & DIBDC, int x, int y, int width, int height)
{
if(DIBDC.m_pData == NULL)
return FALSE;
memcpy(&m_BitmapInfo,&DIBDC.m_BitmapInfo,40);
Height()=height;
Width()=width;
if(!ResetDIB())
return FALSE;
RGBQUAD ColorTable[256];
DIBDC.GetColorTable(ColorTable);
SetColorTable(ColorTable);
BitBlt(0,0,width,height,&DIBDC,x,y,SRCCOPY);
return TRUE;
}
BOOL CDIBDC::CreateDIB(CDIBDC & DIBDC)
{
if(DIBDC.m_pData == NULL)
return FALSE;
if(&DIBDC == this)
return TRUE;
memcpy(&m_BitmapInfo,&DIBDC.m_BitmapInfo,40);
if(!ResetDIB())
return FALSE;
memcpy(m_pData,DIBDC.m_pData,ImageSize());
if(Bits()<=8)
{
RGBQUAD ColorTable[256];
DIBDC.GetColorTable(ColorTable);
SetColorTable(ColorTable);
}
return TRUE;
}
CDIBDC::CDIBDC(CDIBDC & DIBDC)
{
m_hDIBitmap = NULL;
m_Index=NULL;
m_pData=NULL;
CDC::CreateCompatibleDC(&DIBDC);
CreateDIB(DIBDC);
}
CDIBDC& CDIBDC::operator=(CDIBDC& DIBDC)
{
if(&DIBDC == this)
return (*this);
DestroyDIB();
CreateCompatibleDC(&DIBDC);
CreateDIB(DIBDC);
return (*this);
}
BOOL CDIBDC::GetFromFile(CFile *pFile)
{
CString suffix=pFile->GetFileName();
int PointAt=suffix.Find('.');
do
{
suffix=suffix.Mid(PointAt+1);
}
while((PointAt=suffix.Find('.'))!=-1);
suffix.MakeLower();
if(suffix=="bmp")
{
return GetBitmap(pFile);
}
if(suffix=="fri")
{
return GetFreeImage(pFile);
}
if(suffix=="bmc")
{
return GetCrypticBmp(pFile);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -