Click here to Skip to main content
15,114,611 members
Articles / Programming Languages / C++
Alternative
Tip/Trick
Posted 10 Apr 2011

Tagged as

Stats

20.6K views
3 bookmarked

A very basic alpha blend algorithm

Rate me:
Please Sign up or sign in to vote.
4.86/5 (7 votes)
19 Apr 2011CPOL
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)

Share

About the Author

Mukit, Ataul
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 23:52
MemberMukit, Ataul20-Apr-11 23:52 
GeneralRe: Most code can be rewritten to be faster. But almost always, ... Pin
Niklas L20-Apr-11 22:01
MemberNiklas L20-Apr-11 22:01 
GeneralRe: Not sure whether changin the alpha value is a good solution.... Pin
Mukit, Ataul19-Apr-11 21:19
MemberMukit, Ataul19-Apr-11 21:19 
GeneralRe: yes, it's a division by 256. try: int av = uAlphaValue + 1;... Pin
ollienator19-Apr-11 20:50
Memberollienator19-Apr-11 20:50 
GeneralRe: I think >> 8 means division by 256 and not 255. Can anybody ... Pin
Mukit, Ataul19-Apr-11 19:40
MemberMukit, Ataul19-Apr-11 19:40 
GeneralRe: You can unroll the nested loops and just treat them as a con... Pin
basementman14-Apr-11 6:05
Memberbasementman14-Apr-11 6:05 
GeneralRe: as mentioned in your point 4 - "Reordering when necessary mi... Pin
Mukit, Ataul12-Apr-11 1:49
MemberMukit, Ataul12-Apr-11 1:49 
GeneralRe: You're welcome! Pin
Manfred Rudolf Bihy13-Apr-11 11:17
professionalManfred Rudolf Bihy13-Apr-11 11:17 
GeneralI would not worry about people claiming there will be cache ... Pin
Niklas L20-Apr-11 2:34
MemberNiklas L20-Apr-11 2:34 
GeneralRe: Thanx.. that was really inpiring Pin
Mukit, Ataul20-Apr-11 19:52
MemberMukit, Ataul20-Apr-11 19:52 
GeneralRe: Hoi, I have to contradict here a lot. Go use, for instance, ... Pin
gilgamash20-Sep-11 23:06
Membergilgamash20-Sep-11 23:06 
GeneralReason for my vote of 5 Fast and simple thanks. Pin
arm2arm119-Apr-11 0:23
Memberarm2arm119-Apr-11 0:23 
GeneralRe: my pleasure.. Pin
Mukit, Ataul19-Apr-11 0:25
MemberMukit, Ataul19-Apr-11 0:25 
GeneralThis short paper explains it well and thoroughly: http://sy... Pin
gilgamash12-Apr-11 2:36
Membergilgamash12-Apr-11 2:36 
GeneralYou can make it still faster: 1) Replace the divisions by ... Pin
gilgamash12-Apr-11 1:29
Membergilgamash12-Apr-11 1:29 
GeneralRe: All i can say is "WOW!!" .. Thnx... it mite really help in f... Pin
Mukit, Ataul12-Apr-11 1:43
MemberMukit, Ataul12-Apr-11 1:43 
GeneralRe: why not replace /255 with >>8 ? Pin
ollienator19-Apr-11 7:26
Memberollienator19-Apr-11 7:26 
GeneralReason for my vote of 5 Nice! Pin
Manfred Rudolf Bihy11-Apr-11 4:39
professionalManfred Rudolf Bihy11-Apr-11 4:39 
GeneralRe: Finally some appreciation.. thanx :) Pin
Mukit, Ataul11-Apr-11 22:44
MemberMukit, Ataul11-Apr-11 22: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.