BOOL LoadBMPImage(LPCTSTR sBMPFile,
CBitmap& bitmap,
CPalette *pPal)
{
CFile file;
if( !file.Open( sBMPFile, CFile::modeRead) )
return FALSE;
BITMAPFILEHEADER bmfHeader;
Nach dem Öffnen der Datei wird zunächst überprüft, ob es sich um eine BMP-Datei handelt, was an der Signatur „BM“ im ersten Wort zu erkennen ist.
if (file.Read((LPSTR)&bmfHeader,
sizeof(bmfHeader)) != sizeof(bmfHeader))
return FALSE;
if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B'))
return FALSE;
Liegt eine gültige BMP-Datei vor, kann nun die Länge der verbleibenden Datei bestimmt und ausreichend Speicher zur Aufnahme der Datei allokiert und der Rest der Datei anschließend in diesen Speicherbereich geladen werden.
DWORD nPackedDIBLen = file.GetLength() -
sizeof(BITMAPFILEHEADER);
HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen);
if (hDIB == 0)
return FALSE;
if (file.ReadHuge((LPSTR)hDIB, nPackedDIBLen) != nPackedDIBLen )
{
::GlobalFree(hDIB);
return FALSE;
}
Ist das Feld bmiHeader.biClrUsed Null, muß die Anzahl der Farben aus der Anzahl der Bits pro Pixel bestimmt werden.
BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed :
1 << bmiHeader.biBitCount;
LPVOID lpDIBBits;
if( bmInfo.bmiHeader.biBitCount > 8 )
lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors +
bmInfo.bmiHeader.biClrUsed) +
((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ?
3 : 0));
else
lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
Ist pPal ungleich NULL und beträgt die Anzahl der Farben maximal 256, wird eine Palette erzeugt und mit den Werten der Farbtabelle belegt.
if( pPal != NULL )
{
if( nColors <= 256 )
{
UINT nSize = sizeof(LOGPALETTE) +
(sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries = nColors;
for( int i=0; i < nColors; i++)
{
pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
pLP->palPalEntry[i].peFlags = 0;
}
pPal->CreatePalette( pLP );
delete[] pLP;
}
}
Die erzeugte Palette wird nicht nur zurückgeliefert, sondern auch für das Erzeugen des Bitmap-Objekts verwendet. Dazu muß die Palette in den temporären Ausgabekontext selektiert und realisiert werden. Der Kontext nimmt Bezug auf Gerät NULL, also den Default-Bildschirm.
CClientDC dc(NULL);
CPalette* pOldPalette = NULL;
if( pPal )
{
pOldPalette = dc.SelectPalette( pPal, FALSE );
dc.RealizePalette();
}
Die eigentliche Umwandlung erledigt die Funktion CreateDIBitmap, deren Parameter in ihrer Bedeutung im nachfolgenden Aufruf als Kommentar dokumentiert sind.
HBITMAP hBmp = CreateDIBitmap(
dc.m_hDC, // Handle auf Ausgabekontext
&bmiHeader, // Zeiger auf Bitmapgröße und Formatdaten
CBM_INIT, // Flag: Initialisieren
lpDIBBits, // Zeiger auf Initialisierungdaten
&bmInfo, // Zeiger auf Bitmap Farbformatdaten
DIB_RGB_COLORS); // Farbcodierung
bitmap.Attach( hBmp );
if( pOldPalette )
dc.SelectPalette( pOldPalette, FALSE );
::GlobalFree(hDIB);
return TRUE;
}
|