SemiTransparent Bitmaps

This article demonstrates one technique for displaying a semi-transparent bitmap over another one (see image below). Other articles on CodeGuru show you how to display a bitmap with a transparent color (for example, all red pixels are not painted).

Example and source code


void DrawSemiTransparentBitmap(CDC *pDstDC, int x, int y, int nWidth, int nHeight,
    CDC* pSrcDC, int xSrc, int ySrc)
{
    CDC dcCompatible;
    CBitmap *pBitmapOld;
    CBitmap bm;

    dcCompatible.CreateCompatibleDC(pDstDC);
    bm.CreateCompatibleBitmap(pDstDC, nWidth, nHeight);
    pBitmapOld = dcCompatible.SelectObject(&bm);
    dcCompatible.FillSolidRect(CRect(0, 0, nWidth, nHeight), RGB(0x7F, 0x7F, 0x7F));
    pDstDC->BitBlt(x, y, nWidth, nHeight, &dcCompatible, 0, 0, SRCAND);
    dcCompatible.SelectObject(pBitmapOld);

    pDstDC->BitBlt(x, y, nWidth, nHeight, pSrcDC, 0, 0, SRCPAINT);
}
The parameters of this functions are the same as BitBlt except the last one which is not used here.

More information

To display a bitmap (Say A) over another (B) to produce a result where A and B is visible you must divide each pixel of A by a constant, divide each pixel of B by another constant and add the two results.

Result = A*a + B*(1-a)    where "a" is a weight factor 
This method is much slower but produces better results than semi-transparent bitmaps. But if you are interested in speed you should use the semi-transparent method explained here.

The first BitBlt remove the higher bit of each pixel in the destination context and the second add the source context over the destination context. This will result in some saturation of bright colors but is not a problem in most applications.


Result = (A and 0x7F) + B
If you don't worry at all about saturation you can remove all but the last BitBlt. This will result in most case to an image with some saturation if you use bright colors.

Result = A + B
If A and B are big the result could be greater than 255 and result in saturation (modulo).