CBitmap 和CDiB

CBitmap 和CDiB


CBitmap 见msdn 操作设备相关位图
CDib 操作设备相关位图:见visual c++.net  6
//  cdib.h declaration for Inside Visual C++ CDib class

#ifndef _INSIDE_VISUAL_CPP_CDIB
#define  _INSIDE_VISUAL_CPP_CDIB

class  CDib :  public  CObject
{
    
enum Alloc {noAlloc, crtAlloc, heapAlloc};
    DECLARE_SERIAL(CDib)
public:
    LPVOID m_lpvColorTable;
    HBITMAP m_hBitmap;
    LPBYTE m_lpImage;  
// starting address of DIB bits
    LPBITMAPINFOHEADER m_lpBMIH; //  buffer containing the BITMAPINFOHEADER
private:
    HGLOBAL m_hGlobal; 
// For external windows we need to free;
                       
//  could be allocated by this class or allocated externally
    Alloc m_nBmihAlloc;
    Alloc m_nImageAlloc;
    DWORD m_dwSizeImage; 
// of bits -- not BITMAPINFOHEADER or BITMAPFILEHEADER
    int m_nColorTableEntries;
    
    HANDLE m_hFile;
    HANDLE m_hMap;
    LPVOID m_lpvFile;
    HPALETTE m_hPalette;
public:
    CDib();
    CDib(CSize size, 
int nBitCount);    // builds BITMAPINFOHEADER
    ~CDib();
    
int GetSizeImage() {return m_dwSizeImage;}
    
int GetSizeHeader()
        
{return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;}
    CSize GetDimensions();
    BOOL AttachMapFile(
const char* strPathname, BOOL bShare = FALSE);
    BOOL CopyToMapFile(
const char* strPathname);
    BOOL AttachMemory(LPVOID lpvMem, BOOL bMustDelete 
= FALSE, HGLOBAL hGlobal = NULL);
    BOOL Draw(CDC
* pDC, CPoint origin, CSize size);  // until we implemnt CreateDibSection
    HBITMAP CreateSection(CDC* pDC = NULL);
    UINT UsePalette(CDC
* pDC, BOOL bBackground = FALSE);
    BOOL MakePalette();
    BOOL SetSystemPalette(CDC
* pDC);
    BOOL Compress(CDC
* pDC, BOOL bCompress = TRUE); // FALSE means decompress
    HBITMAP CreateBitmap(CDC* pDC);
    BOOL Read(CFile
* pFile);
    BOOL ReadSection(CFile
* pFile, CDC* pDC = NULL);
    BOOL Write(CFile
* pFile);
    
void Serialize(CArchive& ar);
    
void Empty();
private:
    
void DetachMapFile();
    
void ComputePaletteSize(int nBitCount);
    
void ComputeMetrics();
}
;
#endif   //  _INSIDE_VISUAL_CPP_CDIB



//  cdib.cpp
//  new version for WIN32
#include  " stdafx.h "
#include 
" cdib.h "

#ifdef _DEBUG
#define  new DEBUG_NEW
#undef  THIS_FILE
static   char  THIS_FILE[]  =  __FILE__;
#endif

IMPLEMENT_SERIAL(CDib, CObject, 
0 );

CDib::CDib()
{
    m_hFile 
= NULL;
    m_hBitmap 
= NULL;
    m_hPalette 
= NULL;
    m_nBmihAlloc 
= m_nImageAlloc = noAlloc;
    Empty();
}


CDib::CDib(CSize size, 
int  nBitCount)
{
    m_hFile 
= NULL;
    m_hBitmap 
= NULL;
    m_hPalette 
= NULL;
    m_nBmihAlloc 
= m_nImageAlloc = noAlloc;
    Empty();
    ComputePaletteSize(nBitCount);
    m_lpBMIH 
= (LPBITMAPINFOHEADER) new 
        
char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries];
    m_nBmihAlloc 
= crtAlloc;
    m_lpBMIH
->biSize = sizeof(BITMAPINFOHEADER);
    m_lpBMIH
->biWidth = size.cx;
    m_lpBMIH
->biHeight = size.cy;
    m_lpBMIH
->biPlanes = 1;
    m_lpBMIH
->biBitCount = nBitCount;
    m_lpBMIH
->biCompression = BI_RGB;
    m_lpBMIH
->biSizeImage = 0;
    m_lpBMIH
->biXPelsPerMeter = 0;
    m_lpBMIH
->biYPelsPerMeter = 0;
    m_lpBMIH
->biClrUsed = m_nColorTableEntries;
    m_lpBMIH
->biClrImportant = m_nColorTableEntries;
    ComputeMetrics();
    memset(m_lpvColorTable, 
0sizeof(RGBQUAD) * m_nColorTableEntries);
    m_lpImage 
= NULL;  // no data yet
}


CDib::
~ CDib()
{
    Empty();
}


CSize CDib::GetDimensions()
{    
    
if(m_lpBMIH == NULL) return CSize(00);
    
return CSize((int) m_lpBMIH->biWidth, (int) m_lpBMIH->biHeight);
}


BOOL CDib::AttachMapFile(
const   char *  strPathname, BOOL bShare)  //  for reading
{
    
// if we open the same file twice, Windows treats it as 2 separate files
    
// doesn't work with rare BMP files where # palette entries > biClrUsed
    HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ,
        bShare 
? FILE_SHARE_READ : 0,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    ASSERT(hFile 
!= INVALID_HANDLE_VALUE);
    DWORD dwFileSize 
= ::GetFileSize(hFile, NULL);
    HANDLE hMap 
= ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 00, NULL);
    DWORD dwErr 
= ::GetLastError();
    
if(hMap == NULL) {
        AfxMessageBox(
"Empty bitmap file");
        
return FALSE;
    }

    LPVOID lpvFile 
= ::MapViewOfFile(hMap, FILE_MAP_WRITE, 000); // map whole file
    ASSERT(lpvFile != NULL);
    
if(((LPBITMAPFILEHEADER) lpvFile)->bfType != 0x4d42{
        AfxMessageBox(
"Invalid bitmap file");
        DetachMapFile();
        
return FALSE;
    }

    AttachMemory((LPBYTE) lpvFile 
+ sizeof(BITMAPFILEHEADER));
    m_lpvFile 
= lpvFile;
    m_hFile 
= hFile;
    m_hMap 
= hMap;
    
return TRUE;
}


BOOL CDib::CopyToMapFile(
const   char *  strPathname)
{
    
// copies DIB to a new file, releases prior pointers
    
// if you previously used CreateSection, the HBITMAP will be NULL (and unusable)
    BITMAPFILEHEADER bmfh;
    bmfh.bfType 
= 0x4d42;  // 'BM'
    bmfh.bfSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) +
            
sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER);
    
// meaning of bfSize open to interpretation
    bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
    bmfh.bfOffBits 
= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
            
sizeof(RGBQUAD) * m_nColorTableEntries;    
    HANDLE hFile 
= ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL,
        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    ASSERT(hFile 
!= INVALID_HANDLE_VALUE);
    
int nSize =  sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
                
sizeof(RGBQUAD) * m_nColorTableEntries +  m_dwSizeImage;
    HANDLE hMap 
= ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, nSize, NULL);
    DWORD dwErr 
= ::GetLastError();
    ASSERT(hMap 
!= NULL);
    LPVOID lpvFile 
= ::MapViewOfFile(hMap, FILE_MAP_WRITE, 000); // map whole file
    ASSERT(lpvFile != NULL);
    LPBYTE lpbCurrent 
= (LPBYTE) lpvFile;
    memcpy(lpbCurrent, 
&bmfh, sizeof(BITMAPFILEHEADER)); // file header
    lpbCurrent += sizeof(BITMAPFILEHEADER);
    LPBITMAPINFOHEADER lpBMIH 
= (LPBITMAPINFOHEADER) lpbCurrent;
    memcpy(lpbCurrent, m_lpBMIH,
        
sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries); // info
    lpbCurrent += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
    memcpy(lpbCurrent, m_lpImage, m_dwSizeImage); 
// bit image
    DWORD dwSizeImage = m_dwSizeImage;
    Empty();
    m_dwSizeImage 
= dwSizeImage;
    m_nBmihAlloc 
= m_nImageAlloc = noAlloc;
    m_lpBMIH 
= lpBMIH;
    m_lpImage 
= lpbCurrent;
    m_hFile 
= hFile;
    m_hMap 
= hMap;
    m_lpvFile 
= lpvFile;
    ComputePaletteSize(m_lpBMIH
->biBitCount);
    ComputeMetrics();
    MakePalette();
    
return TRUE;
}


BOOL CDib::AttachMemory(LPVOID lpvMem, BOOL bMustDelete, HGLOBAL hGlobal)
{
    
// assumes contiguous BITMAPINFOHEADER, color table, image
    
// color table could be zero length
    Empty();
    m_hGlobal 
= hGlobal;
    
if(bMustDelete == FALSE) {
        m_nBmihAlloc 
= noAlloc;
    }

    
else {
        m_nBmihAlloc 
= ((hGlobal == NULL) ? crtAlloc : heapAlloc);
    }

    
try {
        m_lpBMIH 
= (LPBITMAPINFOHEADER) lpvMem;
        ComputeMetrics();
        ComputePaletteSize(m_lpBMIH
->biBitCount);
        m_lpImage 
= (LPBYTE) m_lpvColorTable + sizeof(RGBQUAD) * m_nColorTableEntries;
        MakePalette();
    }

    
catch(CException* pe) {
        AfxMessageBox(
"AttachMemory error");
        pe
->Delete();
        
return FALSE;
    }

    
return TRUE;
}


UINT CDib::UsePalette(CDC
*  pDC, BOOL bBackground  /**/ /* = FALSE */ )
{
    
if(m_hPalette == NULL) return 0;
    HDC hdc 
= pDC->GetSafeHdc();
    ::SelectPalette(hdc, m_hPalette, bBackground);
    
return ::RealizePalette(hdc);
}


BOOL CDib::Draw(CDC
*  pDC, CPoint origin, CSize size)
{
    
if(m_lpBMIH == NULL) return FALSE;
    
if(m_hPalette != NULL) {
        ::SelectPalette(pDC
->GetSafeHdc(), m_hPalette, TRUE);
    }

    pDC
->SetStretchBltMode(COLORONCOLOR);
    ::StretchDIBits(pDC
->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,
        
00, m_lpBMIH->biWidth, m_lpBMIH->biHeight,
        m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS, SRCCOPY);
    
return TRUE;
}


HBITMAP CDib::CreateSection(CDC
*  pDC  /**/ /* = NULL */ )
{
    
if(m_lpBMIH == NULL) return NULL;
    
if(m_lpImage != NULL) return NULL; // can only do this if image doesn't exist
    m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,
        DIB_RGB_COLORS,    (LPVOID
*&m_lpImage, NULL, 0);
    ASSERT(m_lpImage 
!= NULL);
    
return m_hBitmap;
}


BOOL CDib::MakePalette()
{
    
// makes a logical palette (m_hPalette) from the DIB's color table
    
// this palette will be selected and realized prior to drawing the DIB
    if(m_nColorTableEntries == 0return FALSE;
    
if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
    TRACE(
"CDib::MakePalette -- m_nColorTableEntries = %d\n", m_nColorTableEntries);
    LPLOGPALETTE pLogPal 
= (LPLOGPALETTE) new char[2 * sizeof(WORD) +
        m_nColorTableEntries 
* sizeof(PALETTEENTRY)];
    pLogPal
->palVersion = 0x300;
    pLogPal
->palNumEntries = m_nColorTableEntries;
    LPRGBQUAD pDibQuad 
= (LPRGBQUAD) m_lpvColorTable;
    
for(int i = 0; i < m_nColorTableEntries; i++{
        pLogPal
->palPalEntry[i].peRed = pDibQuad->rgbRed;
        pLogPal
->palPalEntry[i].peGreen = pDibQuad->rgbGreen;
        pLogPal
->palPalEntry[i].peBlue = pDibQuad->rgbBlue;
        pLogPal
->palPalEntry[i].peFlags = 0;
        pDibQuad
++;
    }

    m_hPalette 
= ::CreatePalette(pLogPal);
    delete pLogPal;
    
return TRUE;
}
    

BOOL CDib::SetSystemPalette(CDC
*  pDC)
{
    
// if the DIB doesn't have a color table, we can use the system's halftone palette
    if(m_nColorTableEntries != 0return FALSE;
    m_hPalette 
= ::CreateHalftonePalette(pDC->GetSafeHdc());
    
return TRUE;
}


HBITMAP CDib::CreateBitmap(CDC
*  pDC)
{
    
if (m_dwSizeImage == 0return NULL;
    HBITMAP hBitmap 
= ::CreateDIBitmap(pDC->GetSafeHdc(), m_lpBMIH,
            CBM_INIT, m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS);
    ASSERT(hBitmap 
!= NULL);
    
return hBitmap;
}


BOOL CDib::Compress(CDC
*  pDC, BOOL bCompress  /**/ /* = TRUE */ )
{
    
// 1. makes GDI bitmap from existing DIB
    
// 2. makes a new DIB from GDI bitmap with compression
    
// 3. cleans up the original DIB
    
// 4. puts the new DIB in the object
    if((m_lpBMIH->biBitCount != 4&& (m_lpBMIH->biBitCount != 8)) return FALSE;
        
// compression supported only for 4 bpp and 8 bpp DIBs
    if(m_hBitmap) return FALSE; // can't compress a DIB Section!
    TRACE("Compress: original palette size = %d\n", m_nColorTableEntries); 
    HDC hdc 
= pDC->GetSafeHdc();
    HPALETTE hOldPalette 
= ::SelectPalette(hdc, m_hPalette, FALSE);
    HBITMAP hBitmap;  
// temporary
    if((hBitmap = CreateBitmap(pDC)) == NULL) return FALSE;
    
int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
    LPBITMAPINFOHEADER lpBMIH 
= (LPBITMAPINFOHEADER) new char[nSize];
    memcpy(lpBMIH, m_lpBMIH, nSize);  
// new header
    if(bCompress) {
        
switch (lpBMIH->biBitCount) {
        
case 4:
            lpBMIH
->biCompression = BI_RLE4;
            
break;
        
case 8:
            lpBMIH
->biCompression = BI_RLE8;
            
break;
        
default:
            ASSERT(FALSE);
        }

        
// calls GetDIBits with null data pointer to get size of compressed DIB
        if(!::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight,
                        NULL, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)) 
{
            AfxMessageBox(
"Unable to compress this DIB");
            
// probably a problem with the color table
             ::DeleteObject(hBitmap);
            delete [] lpBMIH;
            ::SelectPalette(hdc, hOldPalette, FALSE);
            
return FALSE; 
        }

        
if (lpBMIH->biSizeImage == 0{
            AfxMessageBox(
"Driver can't do compression");
             ::DeleteObject(hBitmap);
            delete [] lpBMIH;
            ::SelectPalette(hdc, hOldPalette, FALSE);
            
return FALSE; 
        }

        
else {
            m_dwSizeImage 
= lpBMIH->biSizeImage;
        }

    }

    
else {
        lpBMIH
->biCompression = BI_RGB; // decompress
        
// figure the image size from the bitmap width and height
        DWORD dwBytes = ((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) / 32;
        
if(((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) % 32{
            dwBytes
++;
        }

        dwBytes 
*= 4;
        m_dwSizeImage 
= dwBytes * lpBMIH->biHeight; // no compression
        lpBMIH->biSizeImage = m_dwSizeImage;
    }
 
    
// second GetDIBits call to make DIB
    LPBYTE lpImage = (LPBYTE) new char[m_dwSizeImage];
    VERIFY(::GetDIBits(pDC
->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight,
            lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS));
    TRACE(
"dib successfully created - height = %d\n", lpBMIH->biHeight);
    ::DeleteObject(hBitmap);
    Empty();
    m_nBmihAlloc 
= m_nImageAlloc = crtAlloc;
    m_lpBMIH 
= lpBMIH;
    m_lpImage 
= lpImage;
    ComputeMetrics();
    ComputePaletteSize(m_lpBMIH
->biBitCount);
    MakePalette();
    ::SelectPalette(hdc, hOldPalette, FALSE);
    TRACE(
"Compress: new palette size = %d\n", m_nColorTableEntries); 
    
return TRUE;
}


BOOL CDib::Read(CFile
*  pFile)
{
    
// 1. read file header to get size of info hdr + color table
    
// 2. read info hdr (to get image size) and color table
    
// 3. read image
    
// can't use bfSize in file header
    Empty();
    
int nCount, nSize;
    BITMAPFILEHEADER bmfh;
    
try {
        nCount 
= pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
        
if(nCount != sizeof(BITMAPFILEHEADER)) {
            
throw new CUserException;
        }

        
if(bmfh.bfType != 0x4d42{
            
throw new CUserException;
        }

        nSize 
= bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
        m_lpBMIH 
= (LPBITMAPINFOHEADER) new char[nSize];
        m_nBmihAlloc 
= m_nImageAlloc = crtAlloc;
        nCount 
= pFile->Read(m_lpBMIH, nSize); // info hdr & color table
        ComputeMetrics();
        ComputePaletteSize(m_lpBMIH
->biBitCount);
        MakePalette();
        m_lpImage 
= (LPBYTE) new char[m_dwSizeImage];
        nCount 
= pFile->Read(m_lpImage, m_dwSizeImage); // image only
    }

    
catch(CException* pe) {
        AfxMessageBox(
"Read error");
        pe
->Delete();
        
return FALSE;
    }

    
return TRUE;
}


BOOL CDib::ReadSection(CFile
*  pFile, CDC *  pDC  /**/ /* = NULL */ )
{
    
// new function reads BMP from disk and creates a DIB section
    
//    allows modification of bitmaps from disk
    
// 1. read file header to get size of info hdr + color table
    
// 2. read info hdr (to get image size) and color table
    
// 3. create DIB section based on header parms
    
// 4. read image into memory that CreateDibSection allocates
    Empty();
    
int nCount, nSize;
    BITMAPFILEHEADER bmfh;
    
try {
        nCount 
= pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
        
if(nCount != sizeof(BITMAPFILEHEADER)) {
            
throw new CUserException;
        }

        
if(bmfh.bfType != 0x4d42{
            
throw new CUserException;
        }

        nSize 
= bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
        m_lpBMIH 
= (LPBITMAPINFOHEADER) new char[nSize];
        m_nBmihAlloc 
= crtAlloc;
        m_nImageAlloc 
= noAlloc;
        nCount 
= pFile->Read(m_lpBMIH, nSize); // info hdr & color table
        if(m_lpBMIH->biCompression != BI_RGB) {
            
throw new CUserException;
        }

        ComputeMetrics();
        ComputePaletteSize(m_lpBMIH
->biBitCount);
        MakePalette();
        UsePalette(pDC);
        m_hBitmap 
= ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,
            DIB_RGB_COLORS,    (LPVOID
*&m_lpImage, NULL, 0);
        ASSERT(m_lpImage 
!= NULL);
        nCount 
= pFile->Read(m_lpImage, m_dwSizeImage); // image only
    }

    
catch(CException* pe) {
        AfxMessageBox(
"ReadSection error");
        pe
->Delete();
        
return FALSE;
    }

    
return TRUE;
}


BOOL CDib::Write(CFile
*  pFile)
{
    BITMAPFILEHEADER bmfh;
    bmfh.bfType 
= 0x4d42;  // 'BM'
    int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
    bmfh.bfSize 
= 0;
//    bmfh.bfSize = sizeof(BITMAPFILEHEADER) + nSizeHdr + m_dwSizeImage;
    
// meaning of bfSize open to interpretation (bytes, words, dwords?) -- we won't use it
    bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
    bmfh.bfOffBits 
= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
            
sizeof(RGBQUAD) * m_nColorTableEntries;    
    
try {
        pFile
->Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
        pFile
->Write((LPVOID) m_lpBMIH,  nSizeHdr);
        pFile
->Write((LPVOID) m_lpImage, m_dwSizeImage);
    }

    
catch(CException* pe) {
        pe
->Delete();
        AfxMessageBox(
"write error");
        
return FALSE;
    }

    
return TRUE;
}


void  CDib::Serialize(CArchive &  ar)
{
    DWORD dwPos;
    dwPos 
= ar.GetFile()->GetPosition();
    TRACE(
"CDib::Serialize -- pos = %d\n", dwPos);
    ar.Flush();
    dwPos 
= ar.GetFile()->GetPosition();
    TRACE(
"CDib::Serialize -- pos = %d\n", dwPos);
    
if(ar.IsStoring()) {
        Write(ar.GetFile());
    }

    
else {
        Read(ar.GetFile());
    }

}


//  helper functions
void  CDib::ComputePaletteSize( int  nBitCount)
{
    
if((m_lpBMIH == NULL) || (m_lpBMIH->biClrUsed == 0)) {
        
switch(nBitCount) {
            
case 1:
                m_nColorTableEntries 
= 2;
                
break;
            
case 4:
                m_nColorTableEntries 
= 16;
                
break;
            
case 8:
                m_nColorTableEntries 
= 256;
                
break;
            
case 16:
            
case 24:
            
case 32:
                m_nColorTableEntries 
= 0;
                
break;
            
default:
                ASSERT(FALSE);
        }

    }

    
else {
        m_nColorTableEntries 
= m_lpBMIH->biClrUsed;
    }

    ASSERT((m_nColorTableEntries 
>= 0&& (m_nColorTableEntries <= 256)); 
}


void  CDib::ComputeMetrics()
{
    
if(m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {
        TRACE(
"Not a valid Windows bitmap -- probably an OS/2 bitmap\n");
        
throw new CUserException;
    }

    m_dwSizeImage 
= m_lpBMIH->biSizeImage;
    
if(m_dwSizeImage == 0{
        DWORD dwBytes 
= ((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) / 32;
        
if(((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) % 32{
            dwBytes
++;
        }

        dwBytes 
*= 4;
        m_dwSizeImage 
= dwBytes * m_lpBMIH->biHeight; // no compression
    }

    m_lpvColorTable 
= (LPBYTE) m_lpBMIH + sizeof(BITMAPINFOHEADER);
}


void  CDib::Empty()
{
    
// this is supposed to clean up whatever is in the DIB
    DetachMapFile();
    
if(m_nBmihAlloc == crtAlloc) {
        delete [] m_lpBMIH;
    }

    
else if(m_nBmihAlloc == heapAlloc) {
        ::GlobalUnlock(m_hGlobal);
        ::GlobalFree(m_hGlobal);
    }

    
if(m_nImageAlloc == crtAlloc) delete [] m_lpImage;
    
if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
    
if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap);
    m_nBmihAlloc 
= m_nImageAlloc = noAlloc;
    m_hGlobal 
= NULL;
    m_lpBMIH 
= NULL;
    m_lpImage 
= NULL;
    m_lpvColorTable 
= NULL;
    m_nColorTableEntries 
= 0;
    m_dwSizeImage 
= 0;
    m_lpvFile 
= NULL;
    m_hMap 
= NULL;
    m_hFile 
= NULL;
    m_hBitmap 
= NULL;
    m_hPalette 
= NULL;
}


void  CDib::DetachMapFile()
{
    
if(m_hFile == NULL) return;
    ::UnmapViewOfFile(m_lpvFile);
    ::CloseHandle(m_hMap);
    ::CloseHandle(m_hFile);
    m_hFile 
= NULL;
}



你可能感兴趣的:(CBitmap 和CDiB)