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);
void drawBitmapTransparent( CDC* pDC,int aX,int aY,HBITMAP hBitmap,
COLORREF aTransprent); Example: HBITMAP hBitmap;
if (aTransprent == 0)
{
aTransprent = memDC.GetPixel(1,1);
}
HBITMAP fadeBitmap(HBITMAP aBitmap,const COLORREF aFadeto,
const int aTransparency = 0);
hBitmap = fadeBitmap( mBitmap,rectColor,mAlpha);
drawBitmap(pDC,0,0,hBitmap);
void hgradient(CDC* pDC,const unsigned int aClrSrc,
const unsigned int aClrDest,const CRect aRect);
vgradient(pDC,RGB(255,0,0),RGB(255,255,255),
CRect(CPoint(0,160),CSize(50,160)));
HBITMAP getResizeBitmap( HBITMAP hBitmap ,const unsigned int aW,
const unsigned int aH);
mBitmap,100,100);
--------------------------------Header File------------------------------------
#ifndef _CPlayColor_H_
#define _CPlayColor_H_
class CPlayColor
{
public:
CRect mClientRect;
CRect mDirtyRect;
int mAlpha;
CPoint mPoint;
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];
HBITMAP mBitmap;
HBITMAP mBitmapCheck;
HBITMAP mBitmapCheckTrans;
};
#endif
------------------------------------------------------------------------------
--------------------------------CPP File------------------------------------
#include "stdafx.h"
#include "AlphaBlending.h"
#include "PlayColor.h"
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);
CPoint(10,180),mBitmapCheck,0);
mPoint = CPoint(10,180);
}
CPlayColor::~CPlayColor()
{
}
void CPlayColor::draw(CDC* pDC)
{
COLORREF rectColor = RGB(0,124,125);
unsigned aFadeto = RGB(255,255,255);
HBITMAP hBitmap;
HBITMAP hBitmapDirty;
CDC memDCDirty;
hBitmapDirty = getResizeBitmap( mBitmap,mClientRect.Width(),mClientRect.Height() );
memDCDirty.CreateCompatibleDC( NULL );
HBITMAP hBmOldDirty = (HBITMAP)::SelectObject( memDCDirty.m_hDC, hBitmapDirty );
memDCDirty.FillSolidRect(CRect(CPoint(0,0),CSize(600,600)),rectColor);
hBitmap = fadeBitmap( mBitmap,rectColor,mAlpha);
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);
drawBitmapTransparent(&memDCDirty,mPoint.x,mPoint.y,mBitmapCheck,0);
memDCDirty.SelectObject( hBmOldDirty );
memDCDirty.DeleteDC();
drawBitmap(pDC,0,0,hBitmapDirty);
pDC->FillSolidRect(CRect(CPoint(259,9),CSize(102,102)),aFadeto);
hBitmap = getResizeBitmap( hBitmapDirty,100,100);
drawBitmap(pDC,260,10,hBitmap);
}
void CPlayColor::setGradientColor(const COLORREF aSrcClr,const COLORREF aDestClr)
{
}
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;
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));
memDC.SetTextColor(RGB(255,255,255));
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));
COLORREF cs;
COLORREF dc1 = aTransprent;
if (aTransprent == 0)
{
aTransprent = memDC.GetPixel(1,1);
}
for (int x = 0; x""pSrcDC-"" y=""0;"" />GetPixel(y+aImgCorner.x,x+aImgCorner.y);
dc1 = memDC.GetPixel(y,x);
if (dc1 == aTransprent)
{
dc1 = cs;
}
memDC.SetPixel(y,x,dc1);
}
}
memDC.SelectObject(hBmOld);
memDC.DeleteDC();
bmpSrc.Detach();
return hbitmap;
}
HBITMAP CPlayColor::getCloneBitmap( HBITMAP hBitmap)
{
CDC sourceDC, destDC;
sourceDC.CreateCompatibleDC( NULL );
destDC.CreateCompatibleDC( NULL );
BITMAP bm;
::GetObject( hBitmap, sizeof( bm ), &bm );
HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL),
bm.bmWidth, bm.bmHeight);
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 );
::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)
{
CDC sourceDC, destDC;
sourceDC.CreateCompatibleDC( NULL );
destDC.CreateCompatibleDC( NULL );
BITMAP bm;
::GetObject( hBitmap, sizeof( bm ), &bm );
HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL),aW,aH);
HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
destDC.SetStretchBltMode( HALFTONE);
destDC.StretchBlt(0,0,aW,aH,&sourceDC,0,0,bm.bmWidth, bm.bmHeight,SRCCOPY);
::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);
}
for (int x = 0; x""memDC.GetPixel(y,x);"" y=""0;"" !=""aTransprent)
}
}
}
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.