#include "stdafx.h"
#include "DIB.h"
IMPLEMENT_DYNAMIC(CDIB, CGdiObject);
//
//
// CDIB
//
// É豸ÎÞ¹ØÎ»Í¼Àà(°æ±¾1.0)
//
// Íê³É¹¦ÄÜ:
// É豸ÎÞ¹ØÎ»Í¼µÄ´´½¨,ÏÔʾ,¶ÁÈë,±£´æ,²¶×½Î»Í¼
//
// °æ±¾ËùÓÐ: ÂÞöÁ,ÔøÖ¾
//
//
//¹¹Ô캯Êý
CDIB::CDIB() : CGdiObject()
{
}
//Îö¹ºº¯Êý
CDIB::~CDIB()
{
DeleteObject();
}
//
//
// CreateDIB(int cx, int cy, UINT ibitcount, const void* lpBits)
//
// Íê³É¹¦ÄÜ:
// ´´½¨DIBλͼ
//
// ÊäÈë²ÎÊý:
// ͼÏñ¿í¶È cx
// ͼÏñ¸ß¶È cy
// ͼÏñλÊý ibitcount
// ͼÏñÊý¾Ý lpBits
//
// ·µ»Ø²ÎÊý:
// ÊÇ·ñ³É¹¦
//
//
//´´½¨DIBλͼ
BOOL CDIB::CreateDIB(int cx, int cy, UINT ibitcount, const void* lpBits)
{
ASSERT((ibitcount == 1) || (ibitcount == 4) ||
(ibitcount == 8) || (ibitcount == 16)
|| (ibitcount == 24) ||(ibitcount == 32)) ;
// Create a BITMAPINFOHEADER structure to describe the DIB
//´´½¨ÐÅϢͷ
int iSize = sizeof(BITMAPINFOHEADER);// + 256*sizeof(RGBQUAD);
BITMAPINFO* pBMI;
BYTE *pByte;
switch(ibitcount){
case 8:
iSize += 4*4;
break;
case 1:
case 4:
case 16:
case 24:
case 32:
break;
default:
break;
}
pByte = new BYTE[iSize];
pBMI = (BITMAPINFO*) pByte;
memset(pBMI, 0, iSize);
pBMI->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBMI->bmiHeader.biWidth = cx;
pBMI->bmiHeader.biHeight = cy;
pBMI->bmiHeader.biPlanes = 1;
pBMI->bmiHeader.biBitCount = ibitcount;
pBMI->bmiHeader.biCompression = BI_RGB; // to use this flag.
BOOL bRet = CreateDIBIndirect(pBMI, lpBits);
delete[] pByte;
return(bRet);
}
//
//
// CreateDIBIndirect(LPBITMAPINFO pBMI, const void* lpBits)
//
// Íê³É¹¦ÄÜ:
// ´´½¨DIBλͼ
//
// ÊäÈë²ÎÊý:
// λͼÐÅÏ¢½á¹¹Ö¸Õë pBMI
// ͼÏñÊý¾Ý lpBits
//
// ·µ»Ø²ÎÊý:
// ÊÇ·ñ³É¹¦
//
//
//´´½¨DIBλͼ
BOOL CDIB::CreateDIBIndirect(LPBITMAPINFO pBMI, const void* lpBits)
{
//´Ý»ÙÔ¶ÔÏó
if (m_hObject != NULL)
{
DeleteObject();
}
// Create the DIB section.
//´´½¨
CDC *pDC = new CDC;
pDC->CreateCompatibleDC(NULL);
LPVOID pBits;
HBITMAP hDIB = ::CreateDIBSection(pDC->GetSafeHdc(),
pBMI,
DIB_RGB_COLORS,
&pBits,
NULL,
0);
delete pDC;
ASSERT(hDIB);
ASSERT(pBits);
Attach(hDIB);
//¿½±´Í¼ÏñÊý¾Ý
SetDIBBits(GetWidthBytes() * GetHeight(), lpBits);
return TRUE;
}
//
//
// SetDIBBits(DWORD dwCount,const void * lpBits)
//
// Íê³É¹¦ÄÜ:
// ÉèÖÃͼÏñÊý¾Ý,½« lpBits µÄÊý¾Ý¿½±´ÖÁͼÏñ
//
// ÊäÈë²ÎÊý:
// λͼÊý¾Ý´óС dwCount
// ͼÏñÊý¾Ý lpBits
//
// ·µ»Ø²ÎÊý:
// ¿½±´µÄÊý¾Ý´óС
//
//
// Set DIB's bits
// ÉèÖÃͼÏñÊý¾Ý
DWORD CDIB::SetDIBBits(DWORD dwCount,const void * lpBits)
{
if(lpBits != NULL){
LPVOID pBits = GetBits();
memcpy(pBits,lpBits,dwCount);
return dwCount;
}
return 0;
}
//
//
// GetDIBBits(DWORD dwCount, LPVOID lpBits)
//
// Íê³É¹¦ÄÜ:
// µÃµ½Í¼ÏñÊý¾Ý.
// Èç¹û lpBits Ϊ¿Õ,Ôò·µ»ØÍ¼ÏñÊý¾ÝÖ¸Õë;
// Èç¹û lpBits ²»Îª¿Õ,
// Ôò½«Í¼ÏñÊý¾Ý¿½±´ÖÁ¸ÃÖ¸Õë,
// ²¢·µ»ØÍ¼ÏñÊý¾ÝÖ¸Õë;
//
// ÊäÈë²ÎÊý:
// ¿½±´µÄλͼÊý¾Ý´óС dwCount
// ͼÏñÊý¾Ý lpBits
//
// ·µ»Ø²ÎÊý:
// ͼÏñÊý¾ÝÖ¸Õë
//
//
// Get DIB's bits
// µÃµ½Í¼ÏñÊý¾Ý
LPVOID CDIB::GetDIBBits(DWORD dwCount, LPVOID lpBits)
{
LPVOID pBits = GetBits();
if(lpBits != NULL){
memcpy(lpBits,pBits,dwCount);
return pBits;
}
else{
return pBits;
}
}
//
//
// operator = (CDIB& copy)
//
// Íê³É¹¦ÄÜ:
// ÖØÔØ¸³Öµ·û
//
// ÊäÈë²ÎÊý:
// Òª¿½±´µÄλͼ copy
//
// ·µ»Ø²ÎÊý:
// ÐÂͼÏñÊý¾Ý
//
//
//ÖØÔØ¸³Öµ·û
CDIB& CDIB::operator = (CDIB& copy)
{
DIBSECTION DibSection;
//µÃµ½ÔͼÏñÐÅÏ¢
copy.GetDibSection(&DibSection);
int nSize = DibSection.dsBmih.biClrUsed*sizeof(RGBQUAD) + sizeof(BITMAPINFOHEADER);
//ÉêÇëÐÂͼÏñÐÅϢͷÄÚ´æ
BYTE *pByte = new BYTE[nSize];
//¿½±´ÐÅÏ¢
memcpy(pByte, &(DibSection.dsBmih), sizeof(BITMAPINFOHEADER));
CDC *pdc = copy.GetDC();
//µÃµ½µ÷É«°åÐÅÏ¢
::GetDIBColorTable(pdc->GetSafeHdc(), 0, DibSection.dsBmih.biClrUsed,
(RGBQUAD*)(pByte+sizeof(BITMAPINFOHEADER)));
copy.ReleaseDC(pdc);
//´´½¨ÐÂλͼ
BITMAPINFO *pBMI = (BITMAPINFO*)pByte;
CreateDIBIndirect(pBMI);
//¿½±´Í¼ÏñÐÅÏ¢
int nTotalSize = copy.GetWidthBytes() * copy.GetHeight();
memcpy(GetBits(), copy.GetBits(), nTotalSize);
delete[] pByte;
return(*this);
}
//
//
// SetPalette(UINT uStartIndex, UINT cEntries, CONST RGBQUAD *pColors)
//
// Íê³É¹¦ÄÜ:
// ÉèÖõ÷É«°å
//
// ÊäÈë²ÎÊý:
// µ÷É«°å¿ªÊ¼Ë÷Òý uStartIndex
// µ÷É«°åÈë¿Ú cEntries
// ÑÕÉ«Êý¾Ý pColors
//
// ·µ»Ø²ÎÊý:
// ÎÞ
//
//
// Set the color table in the DIB section.
// ÉèÖõ÷É«°å
void CDIB::SetPalette(UINT uStartIndex, UINT cEntries, CONST RGBQUAD *pColors)
{
HDC hdc = ::CreateCompatibleDC(NULL);
HBITMAP hOld = (HBITMAP)::SelectObject(hdc, m_hObject);
::SetDIBColorTable(hdc, uStartIndex, cEntries, pColors);
::SelectObject(hdc, hOld);
::DeleteObject(hdc);
}
//
//
// SetPalette(CPalette* pPal)
//
// Íê³É¹¦ÄÜ:
// ÉèÖõ÷É«°å
//
// ÊäÈë²ÎÊý:
// µ÷É«°å½á¹¹Ö¸Õë pPal
//
// ·µ»Ø²ÎÊý:
// ÎÞ
//
//
// ÉèÖõ÷É«°å
void CDIB::SetPalette(CPalette* pPal)
{
ASSERT(pPal);
// get the colors from the palette
int iColors = 0;
pPal->GetObject(sizeof(iColors), &iColors);
ASSERT(iColors > 0);
PALETTEENTRY* pPE = new PALETTEENTRY[iColors];
pPal->GetPaletteEntries(0, iColors, pPE);
// Build a table of RGBQUADS
RGBQUAD* pRGB = new RGBQUAD[iColors];
ASSERT(pRGB);
for (int i = 0; i < iColors; i++) {
pRGB[i].rgbRed = pPE[i].peRed;
pRGB[i].rgbGreen = pPE[i].peGreen;
pRGB[i].rgbBlue = pPE[i].peBlue;
pRGB[i].rgbReserved = 0;
}
SetPalette(0, iColors, pRGB);
delete [] pRGB;
delete [] pPE;
}
//
//
// GetDC(void)
//
// Íê³É¹¦ÄÜ:
// µÃµ½ÓëλͼÏà¹ØµÄÉ豸
//
// ÊäÈë²ÎÊý:
// ÎÞ
//
// ·µ»Ø²ÎÊý:
// ÓëλͼÏà¹ØµÄÉ豸ָÕë
//
//
//µÃµ½ÓëλͼÏà¹ØµÄÉ豸
CDC* CDIB::GetDC(void)
{
CDibDC* pdc = new CDibDC;
if(pdc == NULL)
return(NULL);
pdc->CreateCompatibleDC(NULL);
pdc->m_hOld = (HBITMAP)::SelectObject(pdc->GetSafeHdc(), GetSafeHandle());
return(pdc);
}
//
//
// ReleaseDC(CDC *pdc)
//
// Íê³É¹¦ÄÜ:
// µÃµ½ÓëλͼÏà¹ØµÄÉ豸
//
// ÊäÈë²ÎÊý:
// ÓëλͼÏà¹ØµÄÉ豸
//
// ·µ»Ø²ÎÊý:
// ÊÇ·ñ³É¹¦
//
//
//Êͷŵõ½µÄÓëλͼÏà¹ØµÄÉ豸
BOOL CDIB::ReleaseDC(CDC *pdc)
{
ASSERT(pdc != NULL);
if(pdc->IsKindOf(RUNTIME_CLASS(CDibDC))){
delete pdc;
return(TRUE);
}
return(FALSE);
}
#ifdef _DEBUG
void CDIB::Dump(CDumpContext& dc) const
{
CGdiObject::Dump(dc);
if (m_hObject == NULL)
return;
BITMAP bm;
VERIFY(GetObject(sizeof(bm), &bm));
dc << "bm.bmType = " << bm.bmType;
dc << "/nbm.bmHeight = " << bm.bmHeight;
dc << "/nbm.bmWidth = " << bm.bmWidth;
dc << "/nbm.bmWidthBytes = " << bm.bmWidthBytes;
dc << "/nbm.bmPlanes = " << bm.bmPlanes;
dc << "/nbm.bmBitsPixel = " << bm.bmBitsPixel;
dc << "/n";
}
#endif
//
//
// LoadBmp(LPCSTR filename)
//
// Íê³É¹¦ÄÜ:
// ¶ÁÈëͼÏñÎļþ
//
// ÊäÈë²ÎÊý:
// λͼÎļþÃû filename
//
// ·µ»Ø²ÎÊý:
// ÊÇ·ñ³É¹¦(-1Ϊ²»³É¹¦)
//
//
//¶ÁÈëͼÏñÎļþ
int CDIB::LoadBmp(LPCSTR filename)
{
//´ò¿ªÎļþ
CFile file(filename,CFile::modeRead|CFile::shareDenyNone);
WORD bfType;
DWORD bfSize;
//¶ÁÈëÎļþÍ·
file.Read(&bfType,sizeof(WORD));
file.Read(&bfSize,sizeof(DWORD));
if(bfSize <= 0)
{
file.Close();
return -1;
}
//ÊÇ·ñBmpÎļþ
if (bfType != (((WORD)'M'<<8) + 'B'))
{
file.Close();
return -1;
}
DWORD bfOffBits;
//ÕÒµ½Î»Í¼Êý¾ÝÆðÊ¼Æ«ÒÆ²¢¶ÁÈë
file.Seek(2*sizeof(WORD),CFile::current);
file.Read(&bfOffBits,sizeof(DWORD));
LPVOID DibBuf;
DibBuf = (LPVOID)new char[bfSize];
if(DibBuf == NULL)
{
file.Close();
return -1;
}
//¶ÁÈëλͼÊý¾Ý
file.ReadHuge(DibBuf,bfSize);
file.Close();
LPBITMAPINFO pBMI;
int size = bfOffBits - 14;
pBMI = (LPBITMAPINFO)new char[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
//Éú³ÉÐÅϢͷ
memcpy(pBMI,DibBuf,size);
LPVOID lpBits = (LPVOID)((LPSTR)DibBuf + size);
//´´½¨Î»Í¼
CreateDIBIndirect(pBMI, lpBits);
delete pBMI;
delete DibBuf;
return 1;
}
//
//
// GetColorUsed()
//
// Íê³É¹¦ÄÜ:
// µÃµ½Ê¹ÓõÄÑÕÉ«Êý
//
// ÊäÈë²ÎÊý:
// ÎÞ
//
// ·µ»Ø²ÎÊý:
// ÑÕÉ«Êý
//
//
//µÃµ½Ê¹ÓõÄÑÕÉ«Êý
int CDIB::GetColorUsed()
{
LPBITMAPINFOHEADER pBMIH;
DIBSECTION DibSection;
GetDibSection(&DibSection);
pBMIH = &DibSection.dsBmih;
return pBMIH->biClrUsed;
}
//
//
// GetPalette()
//
// Íê³É¹¦ÄÜ:
// µÃµ½Ê¹Óõĵ÷É«°å
//
// ÊäÈë²ÎÊý:
// ÎÞ
//
// ·µ»Ø²ÎÊý:
// µ÷É«°åÖ¸Õë,ÓÃÍêÓ¦ÊÍ·Å
//
//
//µÃµ½Ê¹Óõĵ÷É«°å
CPalette * CDibDC::GetPalette()
{
LOGPALETTE * pLogPal = (LOGPALETTE *)new char[sizeof(LOGPALETTE) +
256 * sizeof(PALETTEENTRY)];
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = 256;
HDC hdc = GetSafeHdc();
RGBQUAD pRGB[256];
::GetDIBColorTable(hdc, 0, 256,pRGB);
for(int i = 0 ; i < 256 ; i ++)
{
pLogPal->palPalEntry[i].peRed = pRGB[i].rgbRed;
pLogPal->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue = pRGB[i].rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
}
CPalette * pPal = NULL;
pPal = new CPalette;
pPal->CreatePalette(pLogPal);
delete pLogPal;
return pPal;
}
//
//
// GetBitmapInfo(void)
//
// Íê³É¹¦ÄÜ:
// µÃµ½Î»Í¼ÐÅÏ¢
//
// ÊäÈë²ÎÊý:
// ÎÞ
//
// ·µ»Ø²ÎÊý:
// λͼÐÅÏ¢Ö¸Õë,ÓÃÍêÓ¦ÊÍ·Å
//
//
//µÃµ½Î»Í¼ÐÅÏ¢
LPBITMAPINFO CDIB::GetBitmapInfo(void)
{
DIBSECTION DibSection;
GetDibSection(&DibSection);
int nSize = DibSection.dsBmih.biClrUsed*sizeof(RGBQUAD) + sizeof(BITMAPINFOHEADER);
BYTE *pByte = new BYTE[nSize];
memcpy(pByte, &(DibSection.dsBmih), sizeof(BITMAPINFOHEADER));
CDC *pdc = GetDC();
::GetDIBColorTable(pdc->GetSafeHdc(), 0, DibSection.dsBmih.biClrUsed,
(RGBQUAD*)(pByte+sizeof(BITMAPINFOHEADER)));
ReleaseDC(pdc);
BITMAPINFO *pBMI = (BITMAPINFO*)pByte;
return(pBMI);
}
//
//
// SaveBmp(LPCSTR filename)
//
// Íê³É¹¦ÄÜ:
// ±£´æÎ»Í¼Îļþ
//
// ÊäÈë²ÎÊý:
// ÎļþÃû filename
//
// ·µ»Ø²ÎÊý:
// ÊÇ·ñ³É¹¦
//
//
//±£´æÎļþ
int CDIB::SaveBmp(LPCSTR filename)
{
BITMAPFILEHEADER hdr;
//´ò¿ªÎļþ
CFile file(filename,CFile::modeWrite|CFile::modeCreate);
//ÎļþÍ·
hdr.bfType = ((WORD)'M'<<8) + 'B';
LPBITMAPINFO pbi = GetBitmapInfo();
PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER) pbi;
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Compute the offset to the array of color indices.
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof (RGBQUAD);
//дÈëÎļþÍ·
file.Write((LPVOID) &hdr, sizeof(BITMAPFILEHEADER));
//дÈëÐÅϢͷ
file.Write((LPVOID) pbih, sizeof(BITMAPINFOHEADER)
+ pbih->biClrUsed * sizeof (RGBQUAD));
// Copy the array of color indices into the .BMP file.
//дÈëÊý¾Ý
int nTotal = pbih->biSizeImage;
LPVOID lpBits = GetBits();
file.WriteHuge(lpBits, nTotal);
//¹Ø±ÕÎļþ
file.Close();
delete pbi;
return 1;
}
//
//
// CaptureDIB(CWnd * pWnd, const CRect& capRect)
//
// Íê³É¹¦ÄÜ:
// ²¶×½´°¿ÚͼÏó
//
// ÊäÈë²ÎÊý:
// ´°¿ÚÖ¸Õë pWnd
// ²¶×½µÄ´óС capRect
//
// ·µ»Ø²ÎÊý:
// ÊÇ·ñ³É¹¦
//
//
//²¶×½´°¿ÚͼÏó
BOOL CDIB::CaptureDIB(CWnd * pWnd, const CRect& capRect)
{
BOOL ret = false;
if(pWnd == NULL)
return false;
CDC * pPlayDc = pWnd->GetDC();
if(pPlayDc == NULL)
return false;
CRect Rect;
if(capRect.IsRectEmpty())
pWnd->GetClientRect(Rect);
else
Rect = capRect;
//µÃµ½Í¼ÏñÑÕÉ«Êý
UINT nBitCount = pPlayDc->GetDeviceCaps(BITSPIXEL);
//´´½¨Î»Í¼
if(CreateDIB(Rect.Width(), Rect.Height(), nBitCount))
{
CDC * pCopyDc = GetDC();
if(pCopyDc == NULL)
{
pWnd->ReleaseDC(pPlayDc);
return false;
}
pWnd->ShowWindow(SW_SHOW);
//²¶×½
if(pCopyDc->BitBlt(0, 0, Rect.Width(), Rect.Height(), pPlayDc, 0, 0, SRCCOPY))
ret = true;
ReleaseDC(pCopyDc);
}
pWnd->ReleaseDC(pPlayDc);
return ret;
}
//
//
// CDibDC
//
// É豸ÎÞ¹ØÎ»Í¼É豸Àà(°æ±¾1.0)
//
// Íê³É¹¦ÄÜ:
// ÓëÉ豸ÎÞ¹ØÎ»Í¼µÄÏà¹ØÁª
//
// °æ±¾ËùÓÐ: ÂÞöÁ,ÔøÖ¾
//
//
IMPLEMENT_DYNAMIC(CDibDC, CDC);
CDibDC::CDibDC()
{
m_hOld = NULL;
}
CDibDC::~CDibDC()
{
if(m_hOld != NULL){
::SelectObject(GetSafeHdc(), m_hOld);
}
}