Transparent Bitmap - True Mask Method
- Copy the section of the screen that is to be affected to a memory bitmap.
- Carry out the bitmap operation on the memory bitmap instead of on the screen.
- Copy the memory bitmap back to the screen.
The result is that only one blt affects the screen, so there is no flicker. We may be using two more blt operations, but the operation will probably be perceived as quicker as there is no flicker.
N.B. Some device memory blts are faster than blts that have to access the screen.
MSDN
I had written the source code provided many months ago now for a project I was working on. When I decided to submit it to CodeGuru I had to look at MSDN again to refresh my memory and help me construct a decent explanation for the technique that I use.
One article in particular is called 'Bitmaps with Transparency by Ron Gery (Microsoft Developer Network Technology Group)'. His explanation of transparent blts is excellent, and I have used this as my reference for constructing the following brief explanation. If you are still a bit unclear I recommend you read some of the articles that helped this one along...
The True Mask Method
True mask blting does not need any modification on the part of the source bitmap to be useful. The masked blt involves a three-step process and a mask that has all transparent pixels set to 1 and all opaque pixels set to 0:
- XOR the source bitmap onto the destination (BitBlt with SRCINVERT). This looks a bit funny, but the second XOR restores the destination to its original state.
- Masking operation. When the mask is ANDed to the destination (BitBlt with SRCAND), all of the transparent pixels leave the destination pixels unchanged, while the opaque pixels set the destination to black. Now the destination has a blacked-out image of the opaque part of the source and an XORed image of itself in the transparent part.
- XOR the source to the destination (BitBlt with SRCINVERT). The transparent pixels are restored to their original state, and the opaque pixels are copied directly from the source.
How do I use it?
The function takes four parameters:
- The device context that you wish to display the bitmap in,
- The horizontal position you wish to draw from,
- the vertical position you wish to draw from,
- and the colour in the bitmap that is considered to be transparent (as a COLORREF).
pBitmap->DrawTransparent(pCDC, xPos, yPos, crTrans);
Before I start getting emails on the subject, I should point out that the techniques described in this article specifically target displays and may not necessarily work on some printer devices.
Source Code
void CCISBitmap::DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour)
{
COLORREF crOldBack = pDC->SetBkColor(m_crWhite);
COLORREF crOldText = pDC->SetTextColor(m_crBlack);
CDC dcImage, dcTrans;
// Create two memory dcs for the image and the mask
dcImage.CreateCompatibleDC(pDC);
dcTrans.CreateCompatibleDC(pDC);
// Select the image into the appropriate dc
CBitmap* pOldBitmapImage = dcImage.SelectObject(this);
// Create the mask bitmap
CBitmap bitmapTrans;
int nWidth = Width();
int nHeight = Height();
bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);
// Select the mask bitmap into the appropriate dc
CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);
// Build mask based on transparent colour
dcImage.SetBkColor(crColour);
dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);
// Do the work - True Mask method - cool if not actual display
pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
// Restore settings
dcImage.SelectObject(pOldBitmapImage);
dcTrans.SelectObject(pOldBitmapTrans);
pDC->SetBkColor(crOldBack);
pDC->SetTextColor(crOldText);
}
Drawing a Bitmap Transparently by Zafir Anjum
This is a similar article on this subject which uses a slightly different technique often referred to as 'The Black Source Method'.
The True Mask method requires no additional work: The mask is built and the source needs no manipulation. The three blts do cause on-screen flicker, but there are only three of them.
The Black Source method requires additional work on the source bitmap: the transparent bits need to be made black. The on-screen flashing is less noticeable with this method, and once the source is set-up with black in the correct places, transparency looks very good. For bitmaps as small as icons, transparency is achieved very smoothly. (This mechanism is the one used by Windows to display icons on the screen.)
Direct Transparent Blts
Some device drivers support transparent blts directly. You can determine this using the C1_TRANSPARENT bit of the CAPS1 capability word returned by the GetDeviceCaps function. A special background mode, NEWTRANSPARENT, indicates that subsequent blts are transparent blts. The current background colour of the destination is the transparent colour. When this capability is available on the driver, the basic transparent blt operation can be performed as follows:
// Only attempt this if device supports functionality.
if(GetDeviceCaps(hdcDest, CAPS1) & C1_TRANSPARENT)
{
// Special transparency background mode
oldMode = SetBkMode(hdcDest, NEWTRANSPARENT);
rgbBk = SetBkColor(hdcDest, rgbTransparent);
// Actual blt is a simple source copy; transparency is automatic.
BitBlt(hdcDest, x, y, dx, dy, hdcSrc, x0, y0, SRCCOPY);
SetBkColor(hdcDest, rgbBk);
SetBkMode(hdcDest, oldMode);
}
This code has been compiled and built with Microsoft Visual C++ Version 5.0 SP3.

Comments
The perfect solution
Posted by Legacy on 01/12/2004 12:00amOriginally posted by: Marcus OBrien
Replywindows bitmap
Posted by Legacy on 12/03/2003 12:00amOriginally posted by: azaj17
1. what is windows bitmaps ?
2. how windows bitmaps function ?
3. where the windows bitmaps useses ?
4. what is important the windows bitmaps ?
ReplyTransparent Bitmap - Performance issues + Direct Transparent Blt woes
Posted by Legacy on 11/21/2003 12:00amOriginally posted by: keesh
Reply(NON-MFC) DrawTransparent
Posted by Legacy on 10/14/2003 12:00amOriginally posted by: Chris Brown
ReplyProblems drawing some icons...
Posted by Legacy on 10/03/2003 12:00amOriginally posted by: Chris
Reply
Here the code for Stretch Transparent Bitmap (2)
Posted by Legacy on 10/01/2003 12:00amOriginally posted by: Doo-Yeoun Cho
ReplyHere the code for Stretch Transparent Bitmap
Posted by Legacy on 06/27/2003 12:00amOriginally posted by: Michel Lajeunesse
ReplyHow to stretch a bitmap in memory?
Posted by Legacy on 08/30/2002 12:00amOriginally posted by: gothing
A bitmap can be draw or stretch on DC. Now I don't need to display it to screen, I stretch it in memory, how to do?
ReplyHow do I draw on top of a bitmap?
Posted by Legacy on 08/12/2002 12:00amOriginally posted by: Rainey
In my appication I have a symbol which I have drawn using the CPaintDC class. I need to be able to display this symbol on top of a bitmap. When I try this, the bitmap is drawn ontop of the symbol so that it cannot be seen. Is the a way of reversing the z-order so that the symbol is drawn after the bitmap and therefore on top of it?
ReplyYou only need two blits - not three IF...
Posted by Legacy on 08/01/2002 12:00amOriginally posted by: David Billen
...if your bitmap has zeros for the pixels you want masked. This is acceptable in most cases because you have a bitmap with one corresponding mask. The only time it wouldn't be possible is to use a single mask with different bitmaps for cookie cutter operations.
The mask should have the bits you want masked off as white, and bits you want to keep as black.
Just AND the mask, (SRCAND), then OR the bitmap, (SRCPAINT).
ReplyLoading, Please Wait ...