📄 dibitmap.cpp
字号:
// Filename: DIBitmap.cpp
#include "stdafx.h"
#include "DIBitmap.h"
IMPLEMENT_DYNAMIC( CDIBitmap, CObject )
////////////////////////////////////////////////
// Constructors & Destructors
CDIBitmap::CDIBitmap()
{
m_pBitmapInfo = NULL;
m_pBits = NULL;
m_wNumColors = 0;
m_wBMISize = 0;
m_dwBitsSize = 0;
}
//CDIBitmap(CBitmap* pBM);
//CDIBitmap(BITMAP bm);
CDIBitmap::~CDIBitmap()
{
DestroyDIB();
}
void CDIBitmap::DestroyDIB()
{
free(m_pBits);
free(m_pBitmapInfo);
m_pBits = NULL;
m_pBitmapInfo = NULL;
m_wNumColors = 0;
m_wBMISize = 0;
m_dwBitsSize = 0;
}
////////////////////////////////////////////////
// Selectors
BOOL CDIBitmap::DIBIsLoaded()
{
return ((m_pBits != NULL) &&
(m_pBitmapInfo != NULL));
}
WORD CDIBitmap::NumberOfColors()
{
ASSERT(m_pBits != NULL);
ASSERT(m_pBitmapInfo != NULL);
return m_wNumColors;
}
DWORD CDIBitmap::DIBDataSize()
{
// ASSERT's will be made in calling routines.
return BitmapInfoSize() + BitsSize();
}
WORD CDIBitmap::BitmapInfoSize()
{
ASSERT(m_pBits != NULL);
ASSERT(m_pBitmapInfo != NULL);
return m_wBMISize;
}
DWORD CDIBitmap::BitsSize()
{
ASSERT(m_pBits != NULL);
ASSERT(m_pBitmapInfo != NULL);
return m_dwBitsSize;
}
////////////////////////////////////////////////
// Operations
BOOL CDIBitmap::GetPalette(CPalette* pPal)
{
ASSERT (pPal != NULL);
ASSERT (m_pBits != NULL);
ASSERT (m_pBitmapInfo != NULL);
WORD numRGBQUADS = NumberOfColors();
if (numRGBQUADS == 0)
{
TRACE0("No palette data available.\n");
return FALSE;
}
LOGPALETTE* pLP = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
numRGBQUADS*sizeof(PALETTEENTRY));
pLP->palVersion = 0x300; // Windows version 3.0 (or better)
pLP->palNumEntries = numRGBQUADS;
for (DWORD i = 0; i < numRGBQUADS; i++)
{
pLP->palPalEntry[i].peRed = m_pBitmapInfo->bmiColors[i].rgbRed;
pLP->palPalEntry[i].peGreen = m_pBitmapInfo->bmiColors[i].rgbGreen;
pLP->palPalEntry[i].peBlue = m_pBitmapInfo->bmiColors[i].rgbBlue;
pLP->palPalEntry[i].peFlags = 0;
}
// Detatch and reallocate any LOGPALETTE structure that may
// already be associated with the CPalette object.
// Note: CreatePalette() will fail w/ an assertion if the
// CPalette object already has a palette.
pPal->DeleteObject();
// Create the new palette based on the LOGPALETTE structure
// built above.
if (!pPal->CreatePalette(pLP))
{
TRACE0("Palette creation failed!");
return FALSE;
}
// We don't need the LOGPALETTE structure anymore
// since we have the completed CPalette object.
free(pLP);
return TRUE;
}
WORD BMIColorCount(BITMAPINFOHEADER* pInfoHeader)
{
WORD numRGBQUADS;
// if 24 bits per pixel and no colors are used, then there is no
// color table information.
if ( (pInfoHeader->biBitCount == 24) &&
(pInfoHeader->biClrUsed == 0) )
{
//m_wBMISize = sizeof(BITMAPINFO);
//pbmInfo = (BITMAPINFO*)malloc(m_wBMISize);
//m_wNumColors = 0;
return 0;
}
else
{
// Compute number of RGBQUAD structures held in the DIB file.
if (pInfoHeader->biClrUsed == 0)
{
// find 2 to the power of biBitCount
numRGBQUADS = 2 << (pInfoHeader->biBitCount-1);
}
else
{
numRGBQUADS = (WORD)pInfoHeader->biClrUsed;
}
// Read in the RGB quad data
//m_wBMISize = sizeof(BITMAPINFO) + numRGBQUADS*sizeof(RGBQUAD);
//pbmInfo = (BITMAPINFO*)malloc( m_wBMISize );
//fileDIB.Read(pbmInfo->bmiColors, numRGBQUADS * sizeof(RGBQUAD));
//m_wNumColors = numRGBQUADS;
return numRGBQUADS;
} // end if -- load RGB quads from DIB
}
BOOL CDIBitmap::LoadFromDIB(const char* lpszFileName)
{
CFile fileDIB;
CFileException e;
// Open the file
if ( !fileDIB.Open(lpszFileName, CFile::modeRead, &e) )
{
TRACE0 ("File could not be opened!\n");
return FALSE;
}
//**** Destroy DIB here!?!
DestroyDIB();
// Store Beginning Of File (BOF) position
DWORD dwBOF = fileDIB.GetPosition();
// Read in the file header
BITMAPFILEHEADER fileHeader;
fileDIB.Read(&fileHeader, sizeof(BITMAPFILEHEADER));
// Make sure its a bitmap file.
if (fileHeader.bfType != 0x4D42) // 0x4D42 == "BM"
{
TRACE0 ("File is not a bitmap!\n");
fileDIB.Close();
return FALSE;
}
// Read in the info header.
BITMAPINFOHEADER infoHeader;
fileDIB.Read(&infoHeader, sizeof(BITMAPINFOHEADER));
// Make sure its in Windows format.
if ( infoHeader.biSize != sizeof(BITMAPINFOHEADER) )
{
// Most likely the file is a presentation manager bitmap
// file. This file is structured using the BITCOREHEADER
// type. Consult your manuals for more information.
TRACE0 ("File is not a Windows Bitmap File!\n");
TRACE0 ("Presentation Manager bitmaps not supported.\n");
fileDIB.Close();
return FALSE;
}
m_wNumColors = BMIColorCount(&infoHeader);
m_wBMISize = sizeof(BITMAPINFO) + m_wNumColors*sizeof(RGBQUAD);
BITMAPINFO* pbmInfo = (BITMAPINFO*)malloc( m_wBMISize );
if (m_wNumColors != 0)
{
fileDIB.Read(pbmInfo->bmiColors, m_wNumColors * sizeof(RGBQUAD));
}
// Finish initializing pbmInfo structure
memcpy(pbmInfo, &infoHeader, sizeof(BITMAPINFOHEADER));
// Now we can read in the actual bitmap bits!
m_dwBitsSize = (DWORD)(fileHeader.bfSize - fileHeader.bfOffBits);
//unsigned int numBits = (unsigned int)(fileHeader.bfSize - fileHeader.bfOffBits);
TRACE1("Number of bits in the bitmap: %u\n", m_dwBitsSize);
if (m_dwBitsSize > 64000)
{
TRACE0("Memory allocation too big for malloc!\n");
fileDIB.Close();
return FALSE;
}
BYTE* pbmBits = (BYTE*)malloc((int)m_dwBitsSize);
if (pbmBits == NULL)
{
TRACE0("Not enough memory for bits!\n");
fileDIB.Close();
return FALSE;
}
fileDIB.Seek( dwBOF + fileHeader.bfOffBits, CFile::begin );
fileDIB.Read( pbmBits, (int)m_dwBitsSize );
m_pBitmapInfo = pbmInfo;
m_pBits = pbmBits;
fileDIB.Close();
//#ifdef _DEBUG
//Dump(afxDump);
//#endif
return TRUE;
}
BOOL CDIBitmap::SaveToDIB(const char* lpszFileName)
{
return FALSE;
}
BOOL CDIBitmap::LoadFromHandle(HGLOBAL &hgDIB, DWORD dwSize)
{
// Make sure handle is valid.
if (hgDIB == NULL)
{
TRACE0("NULL handle was passed to LoadFromHandle().\n");
return FALSE;
}
// Lock memory and retrieve pointer.
BYTE FAR* lpDIB = (BYTE FAR*)::GlobalLock(hgDIB);
// Get BITMAPINFO structure from block of global memory
BITMAPINFO bmiData;
_fmemcpy( &bmiData.bmiHeader, lpDIB, sizeof(BITMAPINFOHEADER) );
// Make sure its in Windows format.
if ( bmiData.bmiHeader.biSize != sizeof(BITMAPINFOHEADER) )
{
// Most likely the mem block is a presentation manager
// bitmap. This is structured using the BITCOREHEADER
// type. Consult your manuals for more information.
TRACE0 ("Memory block is not a Windows Bitmap!\n");
TRACE0 ("Presentation Manager bitmaps not supported.\n");
::GlobalUnlock(hgDIB);
return FALSE;
}
//TRACE1("InfoHeader: Bitmap Size: %ld \n", bmiData.bmiHeader.biSize);
//TRACE1("InfoHeader: Bitmap Width: %ld \n", bmiData.bmiHeader.biWidth);
//TRACE1("InfoHeader: Bitmap Height: %ld \n", bmiData.bmiHeader.biHeight);
//TRACE1("InfoHeader: Bitmap Planes: %u \n", bmiData.bmiHeader.biPlanes);
//TRACE1("InfoHeader: Bitmap Bit Count: %ld \n", bmiData.bmiHeader.biBitCount);
//TRACE1("InfoHeader: Bitmap Clr Used: %u \n", bmiData.bmiHeader.biClrUsed);
//TRACE1("InfoHeader: Bitmap Impt Clrs: %u \n", bmiData.bmiHeader.biClrImportant);
// Remove and reallocate any remenants of an old DIB.
DestroyDIB();
m_wNumColors = BMIColorCount(&bmiData.bmiHeader);
m_wBMISize = sizeof(BITMAPINFO) + m_wNumColors*sizeof(RGBQUAD);
BITMAPINFO* pbmInfo = (BITMAPINFO*)malloc( m_wBMISize );
if (m_wNumColors != 0)
{
_fmemcpy( pbmInfo->bmiColors,
lpDIB + sizeof(BITMAPINFOHEADER),
m_wNumColors * sizeof(RGBQUAD) );
}
// Finish initializing pbmInfo structure
memcpy(pbmInfo, &bmiData.bmiHeader, sizeof(BITMAPINFOHEADER));
// Now we can read in the actual bitmap bits!
m_dwBitsSize = (DWORD)(dwSize - m_wBMISize);
//TRACE1("Number of bytes of bitmap data: %u\n", m_dwBitsSize);
if (m_dwBitsSize > 64000)
{
TRACE0("Memory allocation too big for malloc!\n");
::GlobalUnlock(hgDIB);
return FALSE;
}
BYTE* pbmBits = (BYTE*)malloc((int)m_dwBitsSize);
if (pbmBits == NULL)
{
TRACE0("Not enough memory for bits!\n");
::GlobalUnlock(hgDIB);
return FALSE;
}
_fmemcpy( pbmBits, lpDIB + m_wBMISize, (int)m_dwBitsSize );
::GlobalUnlock(hgDIB);
m_pBitmapInfo = pbmInfo;
m_pBits = pbmBits;
//#ifdef _DEBUG
// Dump(afxDump);
//#endif
return TRUE;
}
BOOL CDIBitmap::SaveToHandle(HGLOBAL &hgDIB)
{
ASSERT(m_pBitmapInfo != NULL);
ASSERT(m_pBits != NULL);
if (hgDIB != NULL)
::GlobalFree(hgDIB); // perhaps GlobalRealloc()?
hgDIB = ::GlobalAlloc( GHND, DIBDataSize() );
if (hgDIB == NULL)
{
TRACE0("GlobalAlloc failed!\n");
return FALSE;
}
BYTE FAR* lpDIB = (BYTE FAR*)::GlobalLock(hgDIB);
_fmemcpy( lpDIB, m_pBitmapInfo, BitmapInfoSize() );
_fmemcpy( lpDIB+BitmapInfoSize(), m_pBits, (int)BitsSize() );
if (::GlobalUnlock(hgDIB) != NULL)
ASSERT(FALSE);
// memory is freed elsewhere
// in our case, during the ODBC clean up.
return TRUE;
}
BOOL CDIBitmap::DrawOnDC (CDC* pDC, int x, int y)
{
BOOL Result;
// Make sure the CDC pointer is valid
if (!pDC)
{
TRACE0("NULL CDC pointer passed to DrawOnDC().\n");
return FALSE;
}
// Select and Realize the palette
CPalette CurPalette;
CPalette* pOldPalette = NULL;
if (GetPalette(&CurPalette))
{
if (pOldPalette = pDC->SelectPalette(&CurPalette, FALSE))
pDC->RealizePalette();
else
TRACE0("DrawOnDC: Error in Selecting Palette.\n");
}
else
{
TRACE0("DrawOnDC: GetPalette returns FALSE.\n");
}
// Block transfer the bitmap to the screen
if (m_pBitmapInfo != NULL)
{
int Width = (int)m_pBitmapInfo->bmiHeader.biWidth;
int Height = (int)m_pBitmapInfo->bmiHeader.biHeight;
Result = ::StretchDIBits(pDC->GetSafeHdc(),
x, y, Width, Height, 0, 0,
Width, Height, m_pBits,
m_pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
}
// return dc to original state
if (pOldPalette)
pDC->SelectPalette(pOldPalette, FALSE);
return Result;
}
#ifdef _DEBUG
void CDIBitmap::AssertValid() const
{
CObject::AssertValid();
}
void CDIBitmap::Dump( CDumpContext& dc ) const
{
CObject::Dump(dc);
if (m_pBitmapInfo == NULL)
{
dc << "m_pBitmapInfo == NULL\n\n";
}
else
{
dc << "\nBITMAPINFOHEADER DATA:\n"
<< "Size: " << m_pBitmapInfo->bmiHeader.biSize
<< "\nWidth: " << m_pBitmapInfo->bmiHeader.biWidth
<< "\nHeight: " << m_pBitmapInfo->bmiHeader.biHeight
<< "\nPlanes: " << m_pBitmapInfo->bmiHeader.biPlanes
<< "\nBit Count: " << m_pBitmapInfo->bmiHeader.biBitCount;
dc << "\nCompression: " << m_pBitmapInfo->bmiHeader.biCompression
<< "\nImage Size: " << m_pBitmapInfo->bmiHeader.biSizeImage
<< "\nXPels/Meter: " << m_pBitmapInfo->bmiHeader.biXPelsPerMeter
<< "\nYPels/Meter: " << m_pBitmapInfo->bmiHeader.biYPelsPerMeter
<< "\nColors Used: " << m_pBitmapInfo->bmiHeader.biClrUsed
<< "\nImport. Clrs: " << m_pBitmapInfo->bmiHeader.biClrImportant
<< "\n\n";
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -