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

如何快速轻松地制作渐变色图像

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.20/5 (10投票s)

2004年2月6日

CPOL
viewsIcon

66062

downloadIcon

1111

想知道 Photoshop 和其他软件是如何生成渐变色的吗?在这里你可以找到简单快速的代码!

Sample Image - Pic.jpg

引言

本文档解释了如何在您的 Windows 应用程序中绘制渐变色。本文档需要一些 MFC 类和 GUI 的基本知识。下面的代码非常简单且注释良好 - 我注释掉了我认为可能需要注释的每一句话。 核心思想是获取两种颜色的 RGB 值,然后使用这些颜色以及介于它们之间的所有 256 种颜色来绘制和填充矩形,从而创建像我们在设置和安装程序中看到的渐变图像。

我仍然是一个初学者程序员,如果您对本文档有任何评论或建议,我将非常乐意收到您的反馈。 另外,如果您有任何问题,可以通过 mohgdeisat@hotmail.com 与我联系。

Gradient.h

#if !defined(AFX_GRADIENT1_H__39634012_8104_4550_A02B_65C0C7553A60__INCLUDED_)
#define AFX_GRADIENT1_H__39634012_8104_4550_A02B_65C0C7553A60__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CGradient  
{
public:
    CGradient(CSize=CSize(800,600));
    virtual ~CGradient();
    //members
    void PrepareVertical(CDC *pDC,UINT RTop,
      UINT GTop,UINT BTOP,UINT RBot,UINT GBot,UINT BBot);
    void PrepareHorizontal(CDC *pDC,UINT RRight, 
      UINT GRight,UINT BRight,UINT RLeft,UINT GLeft,UINT BLeft);
    CSize GetDimensions();
    void  SetDimensions(CSize Size);
    void Draw(CDC *pDC, int xDest,int yDest,int xSrc, 
      int ySrc, int Width, int Height,DWORD Rop);

protected:
    CDC *m_dcMem;
    CSize m_Size;


};

#endif
// !defined(AFX_GRADIENT1_H__39634012_8104_4550_A02B_65C0C7553A60__INCLUDED_)

类的实现代码如下

// Gradient1.cpp: implementation of the CGradient class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Gradient.h"
#include "Gradient1.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

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

CGradient::CGradient(CSize Size)
{
    m_Size=Size;
    m_dcMem=NULL;
}

CGradient::~CGradient()
{
    if(m_dcMem!=NULL)
        delete m_dcMem;
}
CSize CGradient::GetDimensions()
{
    return m_Size;
}

void  CGradient::SetDimensions(CSize Size)
{
    m_Size=Size;
}

void CGradient::PrepareVertical(CDC *pDC,UINT RTop, 
   UINT GTop,UINT BTop,UINT RBot,UINT GBot,UINT BBot)
{
    //Here we will create a memory bitmap and draw the colored bitmap on it
    //using my pretty Algorithm for generating colors.

    //if we have already a drawn DC then delete it so we will not have a
    //memory leak

    if(m_dcMem!=NULL)
    {
        delete m_dcMem;
    }

    //create the Memory Bitmap
    CBitmap Bitmap;
    m_dcMem=new CDC;    //new Device Context
    m_dcMem->CreateCompatibleDC(pDC);    //Make it Compatible with pDC
    m_dcMem->SetMapMode(MM_TEXT);        //Pixels Mapping Mode
    //Make the Bitmap compatible with the memory DC
    Bitmap.CreateCompatibleBitmap(pDC,m_Size.cx,m_Size.cy);    
    //Select the bitmap into the memory DC
    m_dcMem->SelectObject(&Bitmap);
    ////////////////////////////////////////////////////////////////
    ////Drawing The Gradient in a MemDC
    ////////////////////////////////////////////////////////////////
    //ALGORITHM:
    //We will have the RGB values of the color at which we will start
    //and the RGB values of the color at which we will end
    //we will fill 256 rectangles using all colors that lie between
    //these two colors. this is done by moving the R,G, and B values slowly
    //from the Starting color to the Ending Color.
    //For example: if we have RTop=100 and RBot=150 then we will draw 256
    //rectangles colored with the R-values of 100,100+(150-100)/256,
    //100+2*(150-100)/256,100+3*(150-100)/256,...
    //and the same will happen to G and B values.

    //rStep,gStep, and bStep are variables that will be used
    //to hold the values at which R,G,B will be changed respectivily
    //For example: if we have RTop=100 and RBot=150 then 
    //rStep=(150-100)/256 so when we start at R=100 and draw 256 rectangles
    //we will end at R=150 when we finish drawing these rectangles
    double rStep,gStep,bStep;
    double rCount,gCount,bCount;
    double RectHeight=m_Size.cy/256.0;
    const int NUM_COLORS=256;
    //We will start counting from TopColor to BottomColor
    //So we give an initial value of the TopColor
    rCount=RTop;
    gCount=GTop;
    bCount=BTop;
    //Calcualte the step of R,G,B values
    rStep=-((double)RTop-RBot)/NUM_COLORS;
    gStep=-((double)GTop-GBot)/NUM_COLORS;
    bStep=-((double)BTop-BBot)/NUM_COLORS;
    for(int ColorCount=0;ColorCount<NUM_COLORS;ColorCount++)
    {
        //Draw using current RGB values and Change RGB values
        //to represent the next color in the chain
        m_dcMem->FillRect(CRect(0,ColorCount*RectHeight,
           m_Size.cx,(ColorCount+1)*RectHeight),
           &CBrush(RGB(rCount,gCount,bCount)));
        rCount+=rStep;
        gCount+=gStep;
        bCount+=bStep;
    }
}

void CGradient::PrepareHorizontal(CDC *pDC,UINT RLeft, 
  UINT GLeft,UINT BLeft,UINT RRight,UINT GRight,UINT BRight)
{
    if(m_dcMem!=NULL)
    {
        delete m_dcMem;
    }

    CBitmap Bitmap;
    m_dcMem=new CDC;
    m_dcMem->CreateCompatibleDC(pDC);
    m_dcMem->SetMapMode(MM_TEXT);
    Bitmap.CreateCompatibleBitmap(pDC,m_Size.cx,m_Size.cy);
    m_dcMem->SelectObject(&Bitmap);
    ////////////////////////////////////////////////////////////////
    ////Drawing The Gradient in a MemDC
    double rStep,gStep,bStep;
    double rCount,gCount,bCount;
    double RectWidth=m_Size.cx/256.0;
    const int NUM_COLORS=256;
    rCount=RRight;
    gCount=GRight;
    bCount=BRight;
    rStep=-((double)RRight-RLeft)/NUM_COLORS;
    gStep=-((double)GRight-GLeft)/NUM_COLORS;
    bStep=-((double)BRight-BLeft)/NUM_COLORS;

    for(int ColorCount=0;ColorCount<NUM_COLORS;ColorCount++)
    {
        m_dcMem->FillRect(CRect(ColorCount*RectWidth,
           0,(ColorCount+1)*RectWidth,m_Size.cy),
           &CBrush(RGB(rCount,gCount,bCount)));
        rCount+=rStep;
        gCount+=gStep;
        bCount+=bStep;
    }
}

void CGradient::Draw(CDC *pDC, int xDest,int yDest,
   int xSrc, int ySrc, int Width, int Height,DWORD Rop)
{
    //Use BitBlt to Draw on a DC
    
    pDC->BitBlt(xDest,yDest,Width,Height,m_dcMem,xSrc,ySrc,Rop);

}
© . All rights reserved.