Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

GDI+ Bitmap construction from GDI DDB/HPALETTE

368 views
Skip to first unread message

Peter Krnjevic

unread,
Nov 17, 2001, 1:55:01 PM11/17/01
to
I'm having some strange color problems creating palettized Bitmaps from
DDB/HPALETTE combos. Perhaps this has something to do with the following
phrase from the Bitmap::Bitmap(hbm,hpal) docs: "Do not pass to the GDI+
Bitmap constructor a GDI bitmap or a GDI palette that is currently (or was
previously) selected into a device context". Does the "was previously" mean
that any DDB drawn on in a memory context can't be subsequently wrapped in a
Bitmap? Even if the DC has since been released? Is this also true for
DIBSECTIONs?

-Peter


John Hornick [MS]

unread,
Nov 19, 2001, 9:25:44 AM11/19/01
to
Hi,

It does not mean that - you must select the bitmap into a memory DC in
order to draw on it. I've asked our docs folks to clarify that phrase - I
think they were trying to say "was previously selected into a DC, and then
not selected back out".

If you have (or can create) a small self-contained function which
reproduces the bad behavior you describe, please post it here.

Thanks,
- John
Microsoft Developer Support
This posting is provided "AS IS" with no warranties, and confers no rights.

Peter Krnjevic

unread,
Nov 19, 2001, 1:08:42 PM11/19/01
to
This code captures a portion of the screen and trys to turn it into a GDI+
Bitmap. This code is only needed for
8 bit per pixel displays.

This first sample doesn't work properly: the palette gets pretty thoroughly
garbled. Hope you folks can read WTL. <g>
Note that this code creates a DDB instead of a DIBSECTION. While
CreateCompatibleBitmap can create either,
from the screen, only DDBs are possible.

...
CClientDC dcScreen(NULL);
CBitmapHandle bmp;
bmp.CreateCompatibleBitmap(dcScreen,rc.Width(),rc.Height());
CDC dcMem;
dcMem.CreateCompatibleDC(dcScreen);
HBITMAP hbmpOld = dcMem.SelectBitmap( bmp );
dcMem.BitBlt( 0, 0, rc.Width(), rc.Height(), dcScreen, rc.left, rc.top,
SRCCOPY );
dcMem.SelectBitmap( hbmpOld );
// Get the active palette
HPALETTE hpal = GetActivePalette( dcScreen );
ATLASSERT(!IsDIBitmap((HBITMAP)bmp));
Bitmap* bitmap = new Bitmap((HBITMAP)bmp,hpal);
...

Draw the Bitmap back onto the 256 color desktop with DrawImage to see the
problem.
OTOH, starting with DIBSECTION, this hack works:

LPBYTE lpbits = 0;
LPBITMAPINFO lpbi = CreateDIBHeader( rc.Width(), rc.Height(),
bm.bmBitsPixel );
// Copy palette
if (bm.bmBitsPixel == 8)
{
GetSystemPaletteEntries( dcScreen, 0, 256,
reinterpret_cast<LPPALETTEENTRY>(lpbi->bmiColors) );
for (int i=0; i<256; i++)
{
BYTE x = lpbi->bmiColors[i].rgbBlue;
lpbi->bmiColors[i].rgbBlue = lpbi->bmiColors[i].rgbRed;
lpbi->bmiColors[i].rgbRed = x;
}
}
CBitmapHandle bmp;
bmp.CreateDIBSection( dcScreen, lpbi, DIB_RGB_COLORS, (VOID**)&lpbits,
NULL, 0 );
free( lpbi );
Bitmap* bitmap = new Bitmap((HBITMAP)bmp);

Cheers,
Peter

"John Hornick [MS]" <JohnHorni...@microsoft.com> wrote in message
news:uBACxYQ...@cppssbbsa01.microsoft.com...

John Hornick [MS]

unread,
Nov 19, 2001, 4:24:17 PM11/19/01
to
Hi,

Are you sure your bitmap (DDB) is being initialized properly? You aren't
selecting a palette into the memory DC, you're just Blting into the memory
DC using the default palette, which is only the standard system colors.

If you could post a small self-contained Win32 function which reproduces
the problem, we could repro here and/or suggest a workaround.

Finally, depending on what you're going to do with the bitmap, consider
using a 32bpp DIBSection. It's what GDI+ will eventually use internally
anyway. Unless, of course, your intention is to save it off in a palletized
format.

Peter Krnjevic

unread,
Nov 19, 2001, 5:22:01 PM11/19/01
to
Mmmm - an editing mistake. I reproduced this on the fly from memory since
I've since turfed the original.
Adding the SelectPalette stuff still fails.
After supper I'll post a minimal routine that reproduces the problem.

As for a work-around, I already switched to manually manupulating the DIB
palettes and all's well.

BTW, are Bitmaps always 32 bit dibsections internally? 'Cause that could get
pretty expensive memory-wise. Or are
they only converted as needed?

Thanks,
Peter

"John Hornick [MS]" <JohnHorni...@microsoft.com> wrote in message

news:YGEaoCU...@cppssbbsa01.microsoft.com...

Peter Krnjevic

unread,
Nov 19, 2001, 8:30:43 PM11/19/01
to
Supper was great - now back to business.
Here is a minimal piece of vanilla Win32 code that reproduces the problem
nicely:

// NB: display must be in 256 color mode
{
HDC hdcScreen = GetDC(NULL);
UINT width = GetDeviceCaps(hdcScreen,HORZRES);
UINT height = GetDeviceCaps(hdcScreen,VERTRES);
UINT bpp = GetDeviceCaps(hdcScreen,BITSPIXEL);
if (bpp<=8)
{
UINT nColors = GetSystemPaletteEntries(hdcScreen,0,0,NULL);
LPLOGPALETTE lplp =
(LPLOGPALETTE)malloc(sizeof(LOGPALETTE)+(nColors-1)*sizeof(PALETTEENTRY));
lplp->palVersion = 0x300 ;
lplp->palNumEntries = (WORD)nColors;
GetSystemPaletteEntries(hdcScreen,0,nColors,lplp->palPalEntry);
HPALETTE hpal = CreatePalette(lplp);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen,width,height);
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem,hbmp);
HPALETTE hpalOld = (HPALETTE)SelectObject(hdcMem,hpal);
BitBlt(hdcMem,0,0,width,height,hdcScreen,0,0,SRCCOPY);
SelectObject(hdcMem,hbmpOld);
SelectObject(hdcMem,hpalOld);
// clean up
free(lplp);
DeleteDC(hdcMem);
}
// You'll need to change this
Bitmap* bitmap = new Bitmap(hbmp,hpal);
Graphics g(someDC);
g.DrawImage(bitmap,0,0,width,height);
}

Phew!

Thanks,
Peter

"John Hornick [MS]" <JohnHorni...@microsoft.com> wrote in message

news:YGEaoCU...@cppssbbsa01.microsoft.com...

Peter Krnjevic

unread,
Nov 22, 2001, 9:36:24 AM11/22/01
to
Ooops! I see I'm a half-wit - I managed to put this together 3 times,
forgetting to RealizePalette after SelectPalette.

Sorry,
Peter

"Peter Krnjevic" <pet...@nospam.plz> wrote in message
news:eN3VHMWcBHA.2064@tkmsftngp03...

John Hornick [MS]

unread,
Nov 22, 2001, 12:21:04 PM11/22/01
to
Does it still have the problem even with RealizePalette()? (I haven't had a
chance to repro here yet).
0 new messages