荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Deny (孤苦伶仃一个人,哈哈), 信区: Program
标  题: Directly Accessing Pixels in a 24-bit Bitmap
发信站: 荔园晨风BBS站 (Tue Dec 25 20:48:27 2001), 转信

This article describes how to display 24-bit (TrueColor) bitmaps which
are created during run-time by directly accessing the bitmap's bit
image.

The code in this article uses the CDib class, developed by David J.
Kruglinski in his book Inside Visual C++, 4th edition. The CDib class is
 copyrighted by Microsoft, and can be used in your programs as long as
you mention their name. The CDib class is included at the end of this
document.

1. Create a CDib object, and allocate memory.
This will typically be done in CView::OnInitialUpdate, or some such.
It's done in the following way:



        // Create a compatible DC
        CDC* pDC = GetDC();
        ASSERT(pDC);
        CDC dcCompat;
        dcCompat.CreateCompatibleDC(pDC);
        ReleaseDC(pDC);

        // Allocate memory for the bitmap
        m_pDib = new CDib(CSize(XSIZE,YSIZE), // size of the bitmap
                                          24);            // bits per pixel
        VERIFY(m_pDib->CreateSection(&dcCompat));        // allocate memory for
bitmap


2. Fill the bitmap data.
You now have a memory region, allocated by Windows, in which you can
write the output information. This memory region is accessed from
m_pDib->m_lpImage, and contains a series of three-byte (R,G,B) pixels.
As an example, you can get a nice rainbow-color image using the
following code:


        int x,y;
        BYTE* dibits = m_pDib->m_lpImage;
        for(x=0; x<XSIZE; x++)
                for(y=0; y<YSIZE; y++) {
                        *(dibits++) = doc(x,y);               // red
                        *(dibits++) = doc(doc.XSize()-x-1,y); // green
                        *(dibits++) = doc(x,doc.YSize()-y-1); // blue
                }

Where we used the function doc, defined as follows (intended for bitmaps
 of size 512x512 pixels, more or less):


BYTE doc(int x,int y) {
        return (BYTE)(sqrt(x*x+y*y)/4);
}

3. Display the bitmap.
From within CView::OnDraw, use the following to display the bitmap:


        m_pDib->Draw(pDC,m_rectDraw.TopLeft(),m_rectDraw.Size());

where m_rectDraw is a logical-coordinate rectangle defining the position
 in which we want to place the bitmap. The bitmap is shrunk or
expanded using the StretchDIBits function so that it will fit into
this rectangle.

4. Delete the DIB.
Don't forget to deallocate the CDib object when you're done. The
constructor deallocates all memory associate with the DIB, including the
 memory of the actual image.


        delete m_pDib;

File: CDib.h -- CDib class header file


// 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) *
pBMIH->biClrImportant = m_nColorTableEntries;
        ComputeMetrics();
        memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorTableEntries);
        m_lpImage = NULL;  // no data yet
}
#endif // _INSIDE_VISUAL_CPP_CDIB


File CDib.cpp -- CDib class definition file

// 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, 0, sizeof(RGBQUAD) *
m_nColorTableEntries);
        m_lpImage = NULL;  // no data yet
}

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

CSize CDib::GetDimensions()
{
        if(m_lpBMIH == NULL) return CSize(0, 0);
        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, 0, 0,
NULL);
        DWORD dwErr = ::GetLastError();
        if(hMap == NULL) {
                AfxMessageBox("Empty bitmap file");
                return FALSE;
        }
        LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // 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, 0, 0, 0); // 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,
                0, 0, 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 == 0) return 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 != 0) return FALSE;
        m_hPalette = ::CreateHalftonePalette(pDC->GetSafeHdc());
        return TRUE;
}

HBITMAP CDib::CreateBitmap(CDC* pDC)
{
    if (m_dwSizeImage == 0) return 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 CException;
                }
                if(bmfh.bfType != 0x4d42) {
                        throw new CException;
                }
                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 CException;
                }
                if(bmfh.bfType != 0x4d42) {
                        throw new CException;
                }
                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 CException;
                }
                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 CException;
        }
        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;
}



--
 ╭⌒╮ ¤
╭ ╭ ⌒╮
╰ ----╯
///"/"/ 心情预报: 多云到少云,间中会头晕,有时会失魂....
                                                        OICQ:86395
        ftp://192.168.1.201/study/my document

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.1.201]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店