Click here to Skip to main content
15,867,488 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 
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 
I would not worry about people claiming there will be cache misses, or that you should use multiplication or shift operations instead of division. They either have no insight in optimization techniques, or they haven't upgraded their compilers since the last millennium. Some myths die hard. Consider yourself fived.
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.