Visual C++ 7.1Visual C++ 8.0Windows VistaVisual C++ 7.0Windows 2003Windows 2000Visual C++ 6.0高级Windows XPMFC初学者中级开发WindowsC++
淡入效果 - 渐变效果 - Alpha 混合 - 缩略图 - 复制 HBITMAP






2.71/5 (13投票s)
玩转位图颜色的简单方法。

引言
图像相关的任务总是很麻烦。我见过很多关于图像处理的文章,它们都做得很好,但我仍然认为我需要贡献一些东西。在我的文章中,我设计了一个名为PlayColor
的类,读者可以在其中找到解决方案。画布的右上角显示整个画布的预览。
背景
我相信这个世界上的每一个任务都是许多小任务的组合。所以我的思路是每次只处理一个像素。如果我能处理一个像素,我想我也可以处理更多的像素。在这里你会看到在渐变或淡入淡出效果或任何处理中,我只是处理一个像素。例如,以渐变效果为例,其基本原理就是将一种颜色改变为另一种颜色。
Using the Code
这个方法几乎可以完成所有事情
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 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; xGetPixel(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; xSetPixel( y+aX,x+aY,dc1 );
}
}
}
memDC.SelectObject(hBmOld);
memDC.DeleteDC();
bmpSrc.Detach();
}
关注点
在解决问题之前,我一直在思考如何编写自己的渐变效果算法。突然我想,为什么不从一个像素开始呢?所以,从小处着眼,大处着手。有点古怪,不是吗?
历史
- 2008年3月14日:初始发布
图像旋转将在我文章的下一个版本中实现。