65.9K
CodeProject 正在变化。 阅读更多。
Home

淡入效果 - 渐变效果 - Alpha 混合 - 缩略图 - 复制 HBITMAP

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.71/5 (13投票s)

2008年3月14日

CPOL

1分钟阅读

viewsIcon

49643

downloadIcon

954

玩转位图颜色的简单方法。

引言

图像相关的任务总是很麻烦。我见过很多关于图像处理的文章,它们都做得很好,但我仍然认为我需要贡献一些东西。在我的文章中,我设计了一个名为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日:初始发布

图像旋转将在我文章的下一个版本中实现。

© . All rights reserved.