Click here to Skip to main content
15,867,141 members
Articles / Programming Languages / C++
Alternative
Tip/Trick

A very basic alpha blend algorithm

Rate me:
Please Sign up or sign in to vote.
4.86/5 (7 votes)
19 Apr 2011CPOL 26.9K   3   19
SledgeHammer didn't help, so I had to do it myself... here it is again - a super fast improved algorithm compared to the previous one and with no setpixel and getpixel :)void AlphaBlend(CDC* pDC, int xDest, int yDest, int nDestWidth, int nDestHeight, CDC* pSrcDC, int xSrc, int ySrc, BYTE...
SledgeHammer didn't help, so I had to do it myself... here it is again - a super fast improved algorithm compared to the previous one and with no setpixel and getpixel :)

C++
void AlphaBlend(CDC* pDC, int xDest, int yDest, int nDestWidth, int nDestHeight,
   CDC* pSrcDC, int xSrc, int ySrc, BYTE uAlphaValue)
{
    ASSERT(pDC);

    BOOL bProceed = TRUE;

    CDC memDC;
    if(!memDC.CreateCompatibleDC(pDC))
    {
        bProceed = FALSE;
    }

    CBitmap memBmp;
    if(bProceed)
    {
        if(!memBmp.CreateCompatibleBitmap(pDC, nDestWidth, nDestHeight))
        {
            bProceed = FALSE;
        }
    }

    if(bProceed)
    {
        CBitmap* pOldBmp = memDC.SelectObject(&memBmp);

        memDC.BitBlt(0, 0, nDestWidth, nDestHeight, pDC, 0, 0, SRCCOPY);

        int nColorSize = sizeof(COLORREF);
        DWORD dwSize = nDestWidth * nDestHeight * nColorSize;
        BYTE* pBitmapBits = new BYTE [dwSize];
        if(!pBitmapBits || 
               memBmp.GetBitmapBits(dwSize,  pBitmapBits) <= 0)
        {
            memDC.SelectObject(pOldBmp);
            if(pBitmapBits)
            {
                delete[] pBitmapBits;
            }

            return;
        }
        COLORREF* pBits = (COLORREF*)pBitmapBits;

        CBitmap tempBmp;
        tempBmp.CreateCompatibleBitmap(pDC, nDestWidth, nDestHeight);
        CBitmap* pSrcBitmap = pSrcDC->SelectObject(&tempBmp);
        BYTE* pSrcBitmapBits = new BYTE [dwSize];
        if(!pSrcBitmapBits  
         || pSrcBitmap->GetBitmapBits(dwSize,  pSrcBitmapBits) <= 0)
        {
            pSrcDC->SelectObject(pSrcBitmap);
            if(pSrcBitmapBits)
            {
                delete[] pSrcBitmapBits;
            }

            return;
        }
        COLORREF* pSrcBits = (COLORREF*)pSrcBitmapBits;

        pSrcDC->SelectObject(pSrcBitmap);

        CDC* pDestDC = &memDC;

        ASSERT(pDestDC);
        ASSERT(pSrcDC);

        BYTE r1, r2, rDest;
        BYTE g1, g2, gDest;
        BYTE b1, b2, bDest;

        BYTE av = uAlphaValue; // Alpha value BYTE

        BYTE rem = 255 - av; // Remaining fraction

        COLORREF clrPixelDest;
        COLORREF clrPixelSrc;

        for(int dy = yDest, sy = ySrc; dy < nDestHeight; dy++, sy++)
        {
            for(int dx = xDest, sx = xSrc; dx < nDestWidth; dx++, sx++)
            {
                clrPixelDest = pBits[dy * nDestWidth + dx];

                // The bitmap is in reverse order (bottom to top)
                // so the RGBs are in reverse order
                b1 = GetRValue(clrPixelDest);
                g1 = GetGValue(clrPixelDest);
                r1 = GetBValue(clrPixelDest);

                clrPixelSrc = pSrcBits[sy * nDestWidth + sx];

                // The bitmap is in reverse order (bottom to top) 
                // so the RGBs are in reverse order
                b2 = GetRValue(clrPixelSrc);
                g2 = GetGValue(clrPixelSrc);
                r2 = GetBValue(clrPixelSrc);

                rDest = (r1*rem + r2*av) / 255;
                gDest = (g1*rem + g2*av) / 255;
                bDest = (b1*rem + b2*av) / 255;

                // The bitmap is in reverse order (bottom to top) 
                //so the RGBs will be in reverse order
                pBits[dy * nDestWidth + dx] = RGB(bDest, gDest, rDest);
            }
        }

        memBmp.SetBitmapBits(dwSize, pBits);
        pDC->BitBlt(0, 0, nDestWidth, nDestHeight, &memDC, 0, 0, SRCCOPY);

        memDC.SelectObject(pOldBmp);

        delete[] pBitmapBits;
        delete[] pSrcBitmapBits;
    }

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Kotha Technologies
Bangladesh Bangladesh
If you are not in - you are out !
- Chapter 1

Comments and Discussions

 
GeneralRe: Darn!! I missed that delete pBitmapBits part, thanx..!! Code... Pin
Mukit, Ataul20-Apr-11 22:52
Mukit, Ataul20-Apr-11 22:52 
GeneralRe: Most code can be rewritten to be faster. But almost always, ... Pin
Niklas L20-Apr-11 21:01
Niklas L20-Apr-11 21:01 
Most code can be rewritten to be faster. But almost always, this is a trade-off, sacrificing readability and maintainability. Unless you have real-time requirements, gaining those few percents just isn't worth it. Your code is clean and easy to follow, which is why I can spot a potential memory leak Smile | :) See? Maintainability again! You need to delete pBitmapBits just before your second return statement. (You don't have to check for null before deleting, since delete will do that for you.)
GeneralRe: Not sure whether changin the alpha value is a good solution.... Pin
Mukit, Ataul19-Apr-11 20:19
Mukit, Ataul19-Apr-11 20:19 
GeneralRe: yes, it's a division by 256. try: int av = uAlphaValue + 1;... Pin
ollienator19-Apr-11 19:50
ollienator19-Apr-11 19:50 
GeneralRe: I think >> 8 means division by 256 and not 255. Can anybody ... Pin
Mukit, Ataul19-Apr-11 18:40
Mukit, Ataul19-Apr-11 18:40 
GeneralRe: You can unroll the nested loops and just treat them as a con... Pin
basementman14-Apr-11 5:05
basementman14-Apr-11 5:05 
GeneralRe: as mentioned in your point 4 - "Reordering when necessary mi... Pin
Mukit, Ataul12-Apr-11 0:49
Mukit, Ataul12-Apr-11 0:49 
GeneralRe: You're welcome! Pin
Manfred Rudolf Bihy13-Apr-11 10:17
professionalManfred Rudolf Bihy13-Apr-11 10:17 
GeneralI would not worry about people claiming there will be cache ... Pin
Niklas L20-Apr-11 1:34
Niklas L20-Apr-11 1:34 
GeneralRe: Thanx.. that was really inpiring Pin
Mukit, Ataul20-Apr-11 18:52
Mukit, Ataul20-Apr-11 18:52 
GeneralRe: Hoi, I have to contradict here a lot. Go use, for instance, ... Pin
gilgamash20-Sep-11 22:06
gilgamash20-Sep-11 22:06 
GeneralReason for my vote of 5 Fast and simple thanks. Pin
arm2arm118-Apr-11 23:23
arm2arm118-Apr-11 23:23 
GeneralRe: my pleasure.. Pin
Mukit, Ataul18-Apr-11 23:25
Mukit, Ataul18-Apr-11 23:25 
GeneralThis short paper explains it well and thoroughly: http://sy... Pin
gilgamash12-Apr-11 1:36
gilgamash12-Apr-11 1:36 
GeneralYou can make it still faster: 1) Replace the divisions by ... Pin
gilgamash12-Apr-11 0:29
gilgamash12-Apr-11 0:29 
GeneralRe: All i can say is "WOW!!" .. Thnx... it mite really help in f... Pin
Mukit, Ataul12-Apr-11 0:43
Mukit, Ataul12-Apr-11 0:43 
GeneralRe: why not replace /255 with >>8 ? Pin
ollienator19-Apr-11 6:26
ollienator19-Apr-11 6:26 
GeneralReason for my vote of 5 Nice! Pin
Manfred Rudolf Bihy11-Apr-11 3:39
professionalManfred Rudolf Bihy11-Apr-11 3:39 
GeneralRe: Finally some appreciation.. thanx :) Pin
Mukit, Ataul11-Apr-11 21:44
Mukit, Ataul11-Apr-11 21:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.