Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

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

0.00/5 (No votes)
14 Mar 2008 1  
How easy to Play with color of bitmap

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:

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);
//------------------------------------------------- 
--------------------------------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
------------------------------------------------------------------------------
--------------------------------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""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""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""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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here