Using The LinearGradientBrush
Colour gradients in GDI+ are easily accomplished using the various gradient brushes. The simplest gradient brush to use is the LinearGradientBrush which provides a simple colour wash that can be used to fill backgrounds or objects such as Paths and Regions.
The LinearGradientBrush in its simplest mode, provides a range of colours across a certain distance. The chart in figure 1 shows how the red, green and blue values change over a distance covered by the LinearGradientBrush.
Figure 1: Colour as a function of distance.
To fill an area with the LinearGradientBrush you need to specify a start and end colour, a rectangle into which the colour gradient will be placed, an angle at which the gradient will be displayed, in this case 0, and a Boolean value that signifies whether the gradient is to be scaled by the current transform. To draw the gradient shown above, I used the following code:
LinearGradientBrush br=new LinearGradientBrush(
new Rectangle(0,0,600,300),
Color.Yellow,
Color.Blue,
0,
false);
e.Graphics.FillRectangle(br,new Rectangle(0,0,600,300));
The gradient fills the rectangle provided so if it's important that a gradient begins and ends at a certain colour, you'll need to be careful about how you calculate the rectangle for the brush. For example, The following image shows text filled with a gradient brush mapped to the exact rectangle of the text and to the client rectangle. Notice how the colour of the "d" in "World" is different. This is because the gradient in the second line is calculated using the width of the client, not the exact size of the text.
Figure 2: Two different gradients.
The code that produced this effect is shown in the following listing.
StringFormat format = (StringFormat)StringFormat.GenericTypographic.Clone();
//calculate the brush exactly...
Font fn = new Font("Tahoma",75);
SizeF sf = e.Graphics.MeasureString("Hello World",fn,1024,format);
LinearGradientBrush br=new LinearGradientBrush(new RectangleF(50,50,sf.Width,sf.Height),Color.Yellow,Color.Blue,0,false);
e.Graphics.DrawString("Hello World",fn,br,new RectangleF(50,50,sf.Width,sf.Height),format);
br.Dispose();
//now be sloppy about the calculation...
br=new LinearGradientBrush(this.ClientRectangle,Color.Yellow,Color.Blue,0,false);
e.Graphics.DrawString("Hello World",fn,br,new RectangleF(50,200,sf.Width,sf.Height),format);
br.Dispose();
Transforming the brush.
The angle at which the gradient is displayed can be modified by setting a specific angle in the constructor or by modifying the transform of the brush. The code in the following listing creates a gradient that runs at 45 degrees, fills a rectangle, rotates the gradient and draws a thick line using it.
LinearGradientBrush br = new LinearGradientBrush(this.ClientRectangle,Color.White,Color.Black,45.0f,true);
e.Graphics.FillRectangle(br,this.ClientRectangle);
br.RotateTransform(108f,MatrixOrder.Append);
Pen p=new Pen(br,15);
e.Graphics.DrawLine(p,0,0,this.ClientRectangle.Width,this.ClientRectangle.Height);
p.Dispose();
br.Dispose();
Figure 3 shows this code in action.
Figure 3: Transforming a gradient brush
Other transformations, such as scaling, and translation are available via the LinearGradientBrush methods.
Triangular brushes
The chart shown in figure 1 details how the brush modifies colour over distance. A triangular brush does the same thing but enables you to set a peak somewhere in the chart which represents the point at which the end colour is reached whereupon the colour returns to the beginning shade as shown in Figure 4.
Figure 4: A Triangular Brush.
The effect shown in figure 4 can be obtained by using the SetBlendTriangularShape method as shown in the following listing.
LinearGradientBrush br = new LinearGradientBrush(this.ClientRectangle,Color.Yellow,Color.Blue,0,false);
br.SetBlendTriangularShape(0.5f,1.0f);
e.Graphics.FillRectangle(br,this.ClientRectangle);
br.Dispose();
The SetBlendTriangularShape enables you to set the peak at any point from the start of the gradient (0) to the end of the gradient (1).
Non-linear gradients.
The LinearGradientBrush.SetSigmaBellShape method may be used to create a non-linear gradient similar to that shown in figure 5.
Figure 5: A sigma bell curve gradient.
As with the triangular brush, you can set the focus point any distance along the curve and modify the amount of blend that is performed. This curve sets the focus to 0.5 and uses the full blend (1.0) as shown in the following listing.
LinearGradientBrush br = new LinearGradientBrush(this.ClientRectangle,Color.Yellow,Color.Blue,0,false);
br.SetSigmaBellShape(0.5f,1.0f);
e.Graphics.FillRectangle(br,this.ClientRectangle);
br.Dispose();
Blends.
In addition to the sigma bell curve or triangular brush, you can set your own custom blend in which you choose the value of colour at specific points along the distance of the overall gradient. You may set as many waypoints as you like by using a Blend object as shown in the following listing.
LinearGradientBrush br = new LinearGradientBrush(this.ClientRectangle,Color.Black,Color.White,0,false);
Blend bl=new Blend();
bl.Factors=new float[]{0f,0.1f,0.5f,0.7f,1.0f,0f,1.0f,0.5f,0.3f,0.2f,0};
bl.Positions=new float[]{0,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f};
br.Blend=bl;
e.Graphics.FillRectangle(br,this.ClientRectangle);
br.Dispose();
Figure 6 shows how the blend maps the factor to the distance.
Figure 6: The Blend
Multiple colour blends
So far, all the gradients seen have dealt with a set of two colours. The beginning and end colours provided in the constructor. The LinearGradientBrush also has the ability to display a gradient using multiple colours thanks to the InterpolationColors property. This property holds a ColorBlend object which is similar to the Blend but which specifies colours and positions.
The code in the listing below, creates a gradient brush with seven colours that span the width of the brush making a rainbow.
LinearGradientBrush br = new LinearGradientBrush(this.ClientRectangle,Color.Black,Color.Black,0,false);
ColorBlend cb = new ColorBlend();
cb.Positions=new float[7];
int i=0;
for(float f=0;f<=1;f+=1.0f/6)
cb.Positions[i++]=f;
cb.Colors=new Color[]{Color.Red,Color.Orange,Color.Yellow,Color.Green,Color.Blue,Color.Indigo,Color.Violet};
br.InterpolationColors=cb;
e.Graphics.FillRectangle(br,this.ClientRectangle);
Figure 7 shows the ColorBlend in action.
Figure 7: The ColorBlend object used in a gradient.
Wrapping
When a gradient brush is used to fill an area that is larger than it's declared rectangular size, the brush will wrap in much the same way that an image will tile to cover the plane. You can control the wrap mode of the brush to provide the Tile, TileFlipY, TileFlipX and TileFlipXY styles. The WrapMode.Clamp style should not be used as it throws an exception.
The following images show two of these styles.
Tile
TileFlipX
Back to the GDI+ FAQ.
Copyright 2003 Robert W. Powell. All rights reserved.
|