tags:

views:

81

answers:

2

I'm displaying a bitmap using GDI+. After loading the bitmap from a DLL resource I set the background colour (blue - #0000FF) to transparent using TransparentBlt. On Windows Vista and later this works as expected.

However, on a Windows XP system we're testing on this only works when any tooltip (e.g. the "title" property in IE, or Windows Explorer's tooltip shown when hovering the mouse over a file, etc) is displayed. The rest of the time the background colour is still blue.

Has anyone encountered this before, or know of a way to stop this occurring and for the blue to be properly made transparent?

Edit: After further investigation I found that setting colour depth in Windows XP to 16 bit colours instead of 32 bit colours caused TransparentBlt to start working normally again. Obviously this isn't an ideal solution, specifying what colour depth must be used, but does this give any hint to what might be happening?

Edit2: Code sample included.

m_pGDIBitmap = new Gdiplus::Bitmap(_Module.m_hInst, MAKEINTRESOURCE(lImageResource));
m_hMemDC = CreateCompatibleDC(hdc);

Gdiplus::Graphics myGraphics(m_hMemDC);

myGraphics.DrawImage(m_pGDIBitmap, 
    Gdiplus::Rect(0, 0, m_pGDIBitmap->GetWidth(), m_pGDIBitmap->GetHeight()), 
    0, 
    0,
    m_pGDIBitmap->GetWidth(), 
    m_pGDIBitmap->GetHeight(),
    Gdiplus::UnitPixel, &imAtt);

SetStretchBltMode(hdc, HALFTONE);
SetBrushOrgEx(hdc, rcBounds.left, rcBounds.top, NULL);
TransparentBlt(hdc, rcBounds.left, rcBounds.top, iScaledWidth, iScaledHeight, m_hMemDC, 0, 0, iBitmapWidth, iBitmapHeight, GetPixel(m_hMemDC, 0, 0));
+1  A: 

You must show some sample code - the code that loads the bitmap and the code that blits it to display.

From the symptoms that you describe, my guess is that you load the bitmap not in its native format, but in the current display format. This means, that when the bit depth of the bitmap differs from the bit depth of the display, an automatic color space conversion is made. When this happens, the color that you provide to TransparentBlt is actually different from the color in the bitmap.

Possible alternative solutions:

  1. Make sure that the bitmap is loaded in its native format without conversion.

  2. Allow the conversion to take place, but instead of providing a hardcoded color value to TransparentBlt, make a GetPixel of a known "transparent" pixel of the bitmap (like top-left), and provide this value to the TransparentBlt.

qbeuek
Added a code sample. I tried using the GetPixel approach without any luck.
dlanod
Try setting the StretchBltMode to COLORONCOLOR and see what happens. You are resizing the bitmap while blitting, so I'm guessing that your bitmap has only a few "transparent" pixels and using HALFTONE they are interpolated and never match the "transparent" value. When the bit depth is 16 bit, there is a greater chance that it matches, but when the bit depth is 24/32 bits, the matching value is never found.
qbeuek
A: 

What I ended up doing was more of a workaround, but it did work. I changed the background colour to black and added the following code before the DrawImage call:

Gdiplus::ImageAttributes imAtt;
imAtt.SetColorKey(Gdiplus::Color(0, 0, 0), Gdiplus::Color(0, 0, 0), Gdiplus::ColorAdjustTypeBitmap);

For some reason using this with blue as the background didn't work and using TransparentBlt on its own with either colour didn't work, but the combination applied the transparency correctly on the various OSes and colour depths that I tried.

If I had access to a paint program that supported bitmap files with an alpha channel, i.e. 32 bit bitmaps, I suspect making the background explicitly transparent and then using AlphaBlend would have worked as well but I didn't have the ability to try that at the time.

dlanod