Click here to Skip to main content
15,893,663 members
Articles / Desktop Programming / MFC

Fade Effect - Gradient Effect - Alphablending - Thumbnail Image - Copy HBITMAP

Rate me:
Please Sign up or sign in to vote.
2.71/5 (13 votes)
14 Mar 2008CPOL1 min read 49K   937   24   4
How easy to Play with color of bitmap
Image 1

Introduction

Image related task is always painful. I have seen so many articles on image processing. They have done very well, but still I think I need to contribute something. In my article, I have designed only one class named PlayColor where the reader can find the solution. Top right corner shows the preview of the whole canvas.

Background

I believe that every task in this world is a combination of many small tasks. So my thought process was to handle only one pixel at any time. If I can process one pixel, I think I can also process more pixels. Here you will see in gradient or fade effect or any processing, I just handle one pixel. Suppose we take gradient effect, the basic thing behind it is to only change one color to another color.

Using the Code

This method does almost everything:

C++
void fadeColor(const unsigned int aClrSrc,unsigned int& 
aClrDest,const int aPercent = 100); 
//---------------------------Transparent drawing--------------------- 
//This method draw a bitmap transparently. 
void drawBitmapTransparent( CDC* pDC,int aX,int aY,HBITMAP hBitmap,
    COLORREF aTransprent); Example: HBITMAP hBitmap;
//any valid HBITMAP 
//hBitmap = drawBitmapTransparent(pDC,0,0,hBitmap,0);
//IF you provide transparent color then it will be used 
//But if you don't then it will take pixel from 
if (aTransprent == 0) 
{ 
    aTransprent = memDC.GetPixel(1,1);
    //TRANSPARENT COLOR from HBITMAP... 
} 
//---------------------------Fading Effect--------------------------- 
HBITMAP fadeBitmap(HBITMAP aBitmap,const COLORREF aFadeto,
    const int aTransparency = 0); 
// Example: 
//NO EFFECT ON ORIGINAL BITMAP HBITMAP 
hBitmap = fadeBitmap( mBitmap,rectColor,mAlpha); 
//mBitmap ORIGINAL BITMAP 
//hBitmap CONVERTED BITMAP 
drawBitmap(pDC,0,0,hBitmap); 
//-------------------Gradient Effect--------------------------------- 
void hgradient(CDC* pDC,const unsigned int aClrSrc,
    const unsigned int aClrDest,const CRect aRect); 
//Example: 
//VERTICAL GRADIENT RED TO WHILT... 
vgradient(pDC,RGB(255,0,0),RGB(255,255,255),
    CRect(CPoint(0,160),CSize(50,160))); 
//------------------Resize Effect------------------------------------- 
HBITMAP getResizeBitmap( HBITMAP hBitmap ,const unsigned int aW,
    const unsigned int aH); 
//Example: 
//NO EFFECT ON ORIGINAL BITMAP HBITMAP hBitmap = getResizeBitmap( 
    mBitmap,100,100);
//------------------------------------------------- 
C++
--------------------------------Header File------------------------------------

//######################################################################
//# FILENAME: CPlayColor.h
//#
//# DESCRIPTION:    PERFORM Fade effect, Draw bitmap transparently,
//#                    Horizontal gradient, Vertical gradient, Copy HBITMAP,
//#                    Transparent HBITMAP ---bitmap from HBITMAP, Resize HBITMAP,
//#                    GET THE PREVIEW OF WHOLE DRAWING.
//# AUTHOR:        Mohammad Saiful Alam (Jewel)
//# POSITION:    Senior Software Engineer
//# E-MAIL:        saiful.alam@ bjitgroup.com
//# CREATE DATE: 2008/02/1
//#
//# Copyright (c) 2007 BJIT Ltd.
//######################################################################

#ifndef _CPlayColor_H_
#define _CPlayColor_H_

class CPlayColor  
{
public:
    //TEST
    CRect mClientRect;
    CRect mDirtyRect;
    int mAlpha;
    CPoint mPoint;
    //TEST
    CPlayColor();
    virtual ~CPlayColor();
    void draw(CDC* pDC);
    //
    void fadeColor(const unsigned int aClrSrc,unsigned int& aClrDest,
        const int aPercent = 100);
    //
    void hgradient(CDC* pDC,const unsigned int aClrSrc,
        const unsigned int aClrDest,const CRect aRect);
    //
    void vgradient(CDC* pDC,const unsigned int aClrSrc,const unsigned int aClrDest,
        const CRect aRect);
    //
    void setGradientColor(const COLORREF aSrcClr,const COLORREF aDestClr);
    //
    HBITMAP fadeBitmap(
        HBITMAP aBitmap,const COLORREF aFadeto,const int aTransparency = 0);
    //
    HBITMAP getTransparentBitmap( CDC* pSrcDC,CPoint aImgCorner,HBITMAP aBitmap,
        COLORREF aTransprent);
    //
    HBITMAP getCloneBitmap( HBITMAP hBitmap );
    //
    HBITMAP getResizeBitmap( HBITMAP hBitmap ,
        const unsigned int aW,const unsigned int aH);
    //
    void drawBitmap(CDC* pDC,int aX, int aY,  HBITMAP hBitmap);
    //
    void drawBitmapTransparent( CDC* pDC,int aX,int aY,HBITMAP hBitmap,
        COLORREF aTransprent);
private:
    COLORREF mSrcColor[5];
    COLORREF mDestColor[5];
    //USED FOR TEST PURPOSE
    HBITMAP mBitmap;
    HBITMAP mBitmapCheck;
    HBITMAP mBitmapCheckTrans;    
    //NOT NEDDED...ONLY FOR TEST PURPOSE
};

#endif
------------------------------------------------------------------------------
C++
--------------------------------CPP File------------------------------------


//######################################################################
//# FILENAME: CPlayColor.cpp
//#
//# DESCRIPTION:    PERFORM Fade effect, Draw bitmap transparently,
//#                    Horizontal gradient, Vertical gradient, Copy HBITMAP,
//#                    Transparent HBITMAP ---bitmap from HBITMAP
//#                    GET THE PREVIEW OF WHOLE DRAWING.
//# AUTHOR:        Mohammad Saiful Alam (Jewel)
//# POSITION:    Senior Software Engineer
//# E-MAIL:        saiful.alam@ bjitgroup.com
//# CREATE DATE: 2008/02/1
//#
//# Copyright (c) 2007 BJIT Ltd.
//######################################################################

#include "stdafx.h"
#include "AlphaBlending.h"
#include "PlayColor.h"


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPlayColor::CPlayColor()
{
    mSrcColor[0] = RGB(255,255,255);
    mDestColor[0] = RGB(0,0,255);

    mSrcColor[1] = RGB(255,255,255);
    mDestColor[1] = RGB(255,0,0);

    mSrcColor[2] = RGB(255,255,255);
    mDestColor[2] = RGB(0,255,0);

    mSrcColor[2] = RGB(255,255,255);
    mDestColor[3] = RGB(255,255,0);

    mBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle( ),
        MAKEINTRESOURCE(IDB_BITMAP_ME),IMAGE_BITMAP,0,0,LR_DEFAULTSIZE);
    mBitmapCheck = (HBITMAP)LoadImage(AfxGetInstanceHandle( ),
        MAKEINTRESOURCE(IDB_BITMAP_CHECK),IMAGE_BITMAP,0,0,LR_DEFAULTSIZE);
    mAlpha = 0;
    mClientRect = CRect(0,0,0,0);

    //mBitmapCheckTrans = getTransparentBitmap( &memDCDirty,
        CPoint(10,180),mBitmapCheck,0);
    mPoint = CPoint(10,180);
}

CPlayColor::~CPlayColor()
{

}
//
void CPlayColor::draw(CDC* pDC)
{
    COLORREF rectColor = RGB(0,124,125);//BACK COLOR
//    COLORREF rectColor = RGB(124,124,125);//BACK COLOR
    unsigned aFadeto = RGB(255,255,255);
    HBITMAP hBitmap;
    //ALL DRAWING PERFORM IN BITMAP SO THAT WE CAN USE THE BITMAP LATER..
    HBITMAP hBitmapDirty;
    CDC memDCDirty;         
    //DRAWAING STARTED...
    hBitmapDirty = getResizeBitmap( mBitmap,mClientRect.Width(),mClientRect.Height() );
    //LARGE BITMAP TO SUPPORT YOUR DRAWING AREA
    memDCDirty.CreateCompatibleDC( NULL );           
    HBITMAP hBmOldDirty = (HBITMAP)::SelectObject( memDCDirty.m_hDC, hBitmapDirty );    
    memDCDirty.FillSolidRect(CRect(CPoint(0,0),CSize(600,600)),rectColor);

    //DRAW A RECTANGLE WITH ALPHA COLOR
    hBitmap = fadeBitmap( mBitmap,rectColor,mAlpha);//NO EFFECT ON ORIGINAL BITMAP
    drawBitmap(&memDCDirty,0,0,hBitmap);
    
    hBitmap = getResizeBitmap( mBitmap,50,50 );
    drawBitmap(&memDCDirty,150,0,hBitmap);
    //
    vgradient(&memDCDirty,mSrcColor[0],mDestColor[0],CRect(CPoint(0,160),CSize(50,160)));
    hgradient(&memDCDirty,mDestColor[1],mSrcColor[0],
        CRect(CPoint(55,160),CSize(250,50)));
    hgradient(&memDCDirty,mSrcColor[0],mDestColor[2],
        CRect(CPoint(55,160+110),CSize(250,50)));
    vgradient(&memDCDirty,mDestColor[3],mSrcColor[0],
        CRect(CPoint(310,160),CSize(50,160)));
    
    drawBitmap(&memDCDirty,160,200,mBitmapCheck);

    //hBitmap = getTransparentBitmap( &memDCDirty,mPoint,mBitmapCheck,0);
    drawBitmapTransparent(&memDCDirty,mPoint.x,mPoint.y,mBitmapCheck,0);

    memDCDirty.SelectObject( hBmOldDirty );
    memDCDirty.DeleteDC();
    //DRAWAING FINISHED...
//    //DRAW WHOLE BITMAP INTO OUTPUT
    drawBitmap(pDC,0,0,hBitmapDirty);
//    //DRAW THUMBNAIL VIEW OF WHOLE DRAWING
    pDC->FillSolidRect(CRect(CPoint(259,9),CSize(102,102)),aFadeto);
    hBitmap = getResizeBitmap( hBitmapDirty,100,100);
    drawBitmap(pDC,260,10,hBitmap);//thumbnail image
}
//
void CPlayColor::setGradientColor(const COLORREF aSrcClr,const COLORREF aDestClr)
{

}

//IF U CAN TRANSLATE ONE COLOR U CAN TRANSLATE WHOLE IMAGE...
void CPlayColor::fadeColor(const unsigned int aClrSrc,
    unsigned int& aClrDest,const int aPercent)
{
    register int rr,gg,bb,dr,dg,db,r1,g1,b1,r2,g2,b2;
    register int f1,f2,f3;
    
    r1 = (aClrSrc)&0xff;
    g1 = ((aClrSrc)>>8)&0xff;
    b1 = ((aClrSrc)>>16)&0xff;


    r2 = (aClrDest)&0xff;
    g2 = ((aClrDest)>>8)&0xff;
    b2 = ((aClrDest)>>16)&0xff;

    rr = r1 - r2;
    gg = g1 - g2;
    bb = b1 - b2;
    //aPercent = 100 means fully converted to aClrSrc;
    f1 = (rr*aPercent)/100;
    f2 = (gg*aPercent)/100;
    f3 = (bb*aPercent)/100;

    dr = r1 - f1;
    dg = g1 - f2;
    db = b1 - f3;    
    aClrDest = RGB(dr,dg,db);
}
//
void CPlayColor::hgradient(CDC* pDC,
    const unsigned int aClrSrc,const unsigned int aClrDest,const CRect aRect)
{
    register int rw,factor,l,t;
    CRect rg;
    unsigned dc = aClrDest;
    rw = aRect.Width();     
    //
    l = aRect.left;
    t = aRect.top;
    for (int i = 1;i<=rw; i++)
    {
        factor = (i*100)/rw;
        fadeColor(aClrSrc,dc,factor);        
        pDC->FillSolidRect(l,t,1,aRect.Height(),dc);        
        dc = aClrDest;
        l+=1;    
    }
}
//
void CPlayColor::vgradient(CDC* pDC,
    const unsigned int aClrSrc,const unsigned int aClrDest,const CRect aRect)
{
    register int rh,factor,l,t;
    CRect rg;
    unsigned dc = aClrDest;
    rh = aRect.Height();
    //
    l = aRect.left;
    t = aRect.top;
    for (int i = 1;i<=rh; i++)
    {
        factor = (i*100)/rh;
        fadeColor(aClrSrc,dc,factor);        
        pDC->FillSolidRect(l,t,aRect.Width(),1,dc);        
        dc = aClrDest;
        t+=1;    
    }
}
//
HBITMAP CPlayColor::fadeBitmap(HBITMAP aBitmap,
    const COLORREF aFadeto,const int aTransparency )
{
    HBITMAP hbitmap;
    CBitmap bmpSrc;
    BITMAP bmp;
    if(!bmpSrc.Attach(aBitmap))
        return NULL;
    if(!bmpSrc.GetBitmap(&bmp))
        return NULL;
    CDC memDC;
    memDC.CreateCompatibleDC( NULL );           
    hbitmap = getCloneBitmap( aBitmap);
    HBITMAP hBmOld = (HBITMAP)::SelectObject( memDC.m_hDC, hbitmap );    
    memDC.SetBkColor(RGB(0,0,0));                // 1 -> black
    memDC.SetTextColor(RGB(255,255,255));        // 0 -> white    
    COLORREF cs;
    unsigned dc1 = aFadeto;

    for (int x = 0; x<bmp.bmheight; hbitmap=""getCloneBitmap("" cs=""memDC.GetPixel(y,x);"" dc1=""aFadeto;"" hbmold=""(HBITMAP)::SelectObject("" y=""0;"" /> black
    memDC.SetTextColor(RGB(255,255,255));        // 0 -> white    
    COLORREF cs;
    COLORREF dc1 = aTransprent;
    if (aTransprent == 0)
    {
        aTransprent = memDC.GetPixel(1,1);//GET LET TOP PIXEL AS TRANSPARENT    
    }
    for (int x = 0; x<bmp.bmheight; cs=""pSrcDC-"" y=""0;"" />GetPixel(y+aImgCorner.x,x+aImgCorner.y);
            dc1 = memDC.GetPixel(y,x);
            if (dc1 == aTransprent)//if this color is same then need to be transparent..
            {
                dc1 = cs;
            }
            memDC.SetPixel(y,x,dc1);
        }
    }    
    memDC.SelectObject(hBmOld);
    memDC.DeleteDC();
    bmpSrc.Detach();    

    return hbitmap;    
}
//CLONE A BITMAP TO ANOTHER...
HBITMAP CPlayColor::getCloneBitmap( HBITMAP hBitmap)
{
    // Create a memory DC compatible with the display
    CDC sourceDC, destDC;
    sourceDC.CreateCompatibleDC( NULL );
    destDC.CreateCompatibleDC( NULL );

    // Get logical coordinates
    BITMAP bm;
    ::GetObject( hBitmap, sizeof( bm ), &bm );

    // Create a bitmap to hold the result
    HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL),
        bm.bmWidth, bm.bmHeight);

    // Select bitmaps into the DCs
    HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
    HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
    destDC.BitBlt( 0, 0, bm.bmWidth, bm.bmHeight, &sourceDC,0,0, SRCCOPY );
    // Reselect the old bitmaps
    ::SelectObject( sourceDC.m_hDC, hbmOldSource );
    ::SelectObject( destDC.m_hDC, hbmOldDest );

    return hbmResult;
}
//
HBITMAP CPlayColor::getResizeBitmap( HBITMAP hBitmap ,
    const unsigned int aW,const unsigned int aH)
{
    // Create a memory DC compatible with the display
    CDC sourceDC, destDC;
    sourceDC.CreateCompatibleDC( NULL );
    destDC.CreateCompatibleDC( NULL );
    // Get logical coordinates
    BITMAP bm;
    ::GetObject( hBitmap, sizeof( bm ), &bm );
    // Create a bitmap to hold the result
    HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL),aW,aH);
    // Select bitmaps into the DCs
    HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
    HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
    
    destDC.SetStretchBltMode( HALFTONE);//for better output
    destDC.StretchBlt(0,0,aW,aH,&sourceDC,0,0,bm.bmWidth, bm.bmHeight,SRCCOPY);
    // Reselect the old bitmaps
    ::SelectObject( sourceDC.m_hDC, hbmOldSource );
    ::SelectObject( destDC.m_hDC, hbmOldDest );
    return hbmResult;
}
//
void CPlayColor::drawBitmap(CDC* pDC,int aX, int aY,  HBITMAP hBitmap)
{
    BITMAP bm;
    CDC memDC;
    memDC.CreateCompatibleDC(NULL);
    ::GetObject( hBitmap, sizeof( bm ), &bm );
    HBITMAP hbmOld = (HBITMAP)memDC.SelectObject(hBitmap);
    pDC->BitBlt( aX,aY,bm.bmWidth,bm.bmHeight,&memDC,0,0,SRCCOPY);
    memDC.SelectObject( hbmOld );
    memDC.DeleteDC();
}
//
void CPlayColor::drawBitmapTransparent( CDC* pDC,int aX,int aY,
    HBITMAP hBitmap,COLORREF aTransprent)
{
    CBitmap bmpSrc;
    BITMAP bmp;
    if(!bmpSrc.Attach(hBitmap))
        return;
    if(!bmpSrc.GetBitmap(&bmp))
        return;
    CDC memDC;
    memDC.CreateCompatibleDC( NULL );           
    HBITMAP hBmOld = (HBITMAP)::SelectObject( memDC.m_hDC, hBitmap );    
    COLORREF dc1 = aTransprent;
    if (aTransprent == 0)
    {
        aTransprent = memDC.GetPixel(1,1);//GET LET TOP PIXEL AS TRANSPARENT    
    }
    for (int x = 0; x<bmp.bmheight; dc1=""memDC.GetPixel(y,x);"" y=""0;"" !=""aTransprent)//if"" />SetPixel( y+aX,x+aY,dc1 );
            }                        
        }
    }    
    memDC.SelectObject(hBmOld);
    memDC.DeleteDC();
    bmpSrc.Detach();    
}        

Points of Interest

Before solving the problem, I was thinking about how I could write my own algorithm for gradient effect. Suddenly I thought, why not begin with only one pixel. So, think small from big. Zany?

History

  • 14th March, 2008: Initial post

Rotation of image will be in the next version of my article.

License

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


Written By
Bangladesh Bangladesh
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralVerify the code for Page Turn Effect Pin
saiful_vonair9-Jun-10 4:15
saiful_vonair9-Jun-10 4:15 
GeneralONE pixel at a time? REALLY?? How insane!! PinPopular
NickVellios6-Jun-08 22:41
NickVellios6-Jun-08 22:41 
GeneralRe: ONE pixel at a time? REALLY?? How insane!! Pin
xliqz5-Apr-09 3:19
xliqz5-Apr-09 3:19 
GeneralRe: ONE pixel at a time? REALLY?? How insane!! Pin
xox_c0bra_xox8-May-10 19:10
xox_c0bra_xox8-May-10 19:10 
Hello,

Wow, this is really good stuff lmfao give some people a for next loop some common objects have then manipulate the bits of an image or the color and they think they are gods.

Dude are you for real? Your a Senior whatever but you are presenting things that are just the basics of any image manipulation. How long did it take you to figure this out lol?

I agree with both people who posted here this article is not only pointless but lacks any skills of a real programmer cause as everyone can see from this source project very little of this code was even written by you, as 90 percent of whats here is MFC Framework.

You didnt even take the time to make each button change to stop you add an extra button and why do all you so called programmers use a dialog as the main window? Whats up with this graphics programs should use a real window and only use dialogs as popups.

A real project from someone Senior would be a SDI with customised dockbars for where your controls are but hey I guess in this world you have to know very little to be a Seinor anything.

Liquid Snake

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.