1.20 1.25a 1.30 3.10 4.00 | 3.50 3.51
WINDOWS | WINDOWS NT
kbgraphic
MORE INFORMATION
Windows and Windows NT
A bitmap (.BMP file) is stored in an application's resources as a (DIB),
along with a color table if one exists. When a DIB is loaded from an
application's resources with the
LoadBitmap function, a DDB is returned. This DDB is a bitmap compatible with the screen. Routines such as
CreateDIBitmap and SetDIBits that convert DIBs to DDBs take a handle to a
device context as their first parameter. This tells the routine what kind
of DDB to create. If this device context currently has a palette selected
into it, then CreateDIBitmap or SetDIBits can use this palette to create
the DDB. Without a palette, the routines are restricted to system colors
when matching the DIB's colors to the DDB's colors. For example, on an 8
bit-per-pixel display, the resulting DDB can have only up to 20 different
colors. With a logical palette, the resulting bitmap could have had up to
256 different colors.
If the bitmap is loaded as a DIB from the resource, then an application can
query the DIB's color table and create a logical palette for the DIB. Then,
it can call either CreateDIBitmap or SetDIBits, along with a device context
with that palette selected, to obtain a DDB compatible with that palette.
To load a bitmap from a resource as a DIB, you can use the
FindResource function with the RT_BITMAP flag set and then use the
LoadResource function to load it. You can lock the resource with the
LockResource function.
The following code demonstrates how to use the above technique to load a
DIB from an application's resources, create a palette for it, and then
create a DDB out of it. The
LoadResourceBitmap function below can be used in place of the
LoadBitmap function. The only additional parameter needed is the address of a logical palette handle. The palette handle referenced will contain a handle to a logical palette after the function is called.
HBITMAP LoadResourceBitmap(HINSTANCE hInstance, LPSTR lpString,
HPALETTE FAR* lphPalette)
{
HRSRC hRsrc;
HGLOBAL hGlobal;
HBITMAP hBitmapFinal = NULL;
LPBITMAPINFOHEADER lpbi;
HDC hdc;
int iNumColors;
if (hRsrc = FindResource(hInstance, lpString, RT_BITMAP))
{
hGlobal = LoadResource(hInstance, hRsrc);
lpbi = (LPBITMAPINFOHEADER)LockResource(hGlobal);
hdc = GetDC(NULL);
*lphPalette = CreateDIBPalette ((LPBITMAPINFO)lpbi, &iNumColors);
if (*lphPalette)
{
SelectPalette(hdc,*lphPalette,FALSE);
RealizePalette(hdc);
}
hBitmapFinal = CreateDIBitmap(hdc,
(LPBITMAPINFOHEADER)lpbi,
(LONG)CBM_INIT,
(LPSTR)lpbi + lpbi->biSize + iNumColors *
sizeof(RGBQUAD),
(LPBITMAPINFO)lpbi,
DIB_RGB_COLORS );
ReleaseDC(NULL,hdc);
UnlockResource(hGlobal);
FreeResource(hGlobal);
}
return (hBitmapFinal);
}
HPALETTE CreateDIBPalette (LPBITMAPINFO lpbmi, LPINT lpiNumColors)
{
LPBITMAPINFOHEADER lpbi;
LPLOGPALETTE lpPal;
HANDLE hLogPal;
HPALETTE hPal = NULL;
int i;
lpbi = (LPBITMAPINFOHEADER)lpbmi;
if (lpbi->biBitCount <= 8)
*lpiNumColors = (1 << lpbi->biBitCount);
else
*lpiNumColors = 0; // No palette needed for 24 BPP DIB
if (lpbi->biClrUsed > 0)
*lpiNumColors = lpbi->biClrUsed; // Use biClrUsed
if (*lpiNumColors)
{
hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +
sizeof (PALETTEENTRY) * (*lpiNumColors));
lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);
lpPal->palVersion = 0x300;
lpPal->palNumEntries = *lpiNumColors;
for (i = 0; i < *lpiNumColors; i++)
{
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
hPal = CreatePalette (lpPal);
GlobalUnlock (hLogPal);
GlobalFree (hLogPal);
}
return hPal;
}
Here is an example of how you might use the above function to load a bitmap
from a resource and display it using a logical palette:
{
HBITMAP hBitmap,hOldBitmap;
HPALETTE hPalette;
HDC hMemDC, hdc;
BITMAP bm;
hBitmap = LoadResourceBitmap(hInst,"test", &hPalette);
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
hdc = GetDC(hWnd);
hMemDC = CreateCompatibleDC(hdc);
SelectPalette(hdc,hPalette,FALSE);
RealizePalette(hdc);
SelectPalette(hMemDC,hPalette,FALSE);
RealizePalette(hMemDC);
hOldBitmap = SelectObject(hMemDC,hBitmap);
BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hMemDC,0,0,SRCCOPY);
DeleteObject(SelectObject(hMemDC,hOldBitmap));
DeleteDC(hMemDC);
ReleaseDC(hWnd,hdc);
DeleteObject(hPalette);
}
Win32s
On Win32s, LoadResource does not return a true global memory handle. This
causes CreateDIBitmap to fail. To work around this problem, use GlobalAlloc
to create a global memory handle.
Here is what LoadResourceBitmap should be on Win32s:
HBITMAP LoadResourceBitmap(HINSTANCE hInstance, LPSTR lpString,
HPALETTE FAR* lphPalette)
{
HRSRC hRsrc;
HGLOBAL hGlobal, hTemp;
DWORD dwSize;
HBITMAP hBitmapFinal = NULL;
LPBITMAPINFOHEADER lpbi;
LPSTR lpRes, lpNew;
HDC hdc;
int iNumColors;
if (hRsrc = FindResource(hInstance, lpString, RT_BITMAP))
{
hTemp = LoadResource(hInstance, hRsrc);
dwSize = SizeofResource(hInstance, hRsrc);
lpRes = LockResource(hTemp);
hGlobal = GlobalAlloc(GHND, dwSize);
lpNew = GlobalLock(hGlobal);
memcpy(lpNew, lpRes, dwSize);
UnlockResource(hTemp);
FreeResource(hTemp);
lpbi = (LPBITMAPINFOHEADER)lpNew;
hdc = GetDC(NULL);
*lphPalette = CreateDIBPalette ((LPBITMAPINFO)lpbi, &iNumColors);
if (*lphPalette)
{
SelectPalette(hdc,*lphPalette,FALSE);
RealizePalette(hdc);
}
hBitmapFinal = CreateDIBitmap(hdc,
(LPBITMAPINFOHEADER)lpbi,
(LONG)CBM_INIT,
(LPSTR)lpbi + lpbi->biSize + iNumColors * sizeof(RGBQUAD),
(LPBITMAPINFO)lpbi,
DIB_RGB_COLORS );
ReleaseDC(NULL,hdc);
GlobalUnlock(hGlobal);
GlobalFree(hGlobal);
}
return (hBitmapFinal);
}