Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C# color gradient control

0.00/5 (No votes)
9 Sep 2015 1  
An implementation of color gradient control in c#, and a use case applied to procedural landscape generation.

Introduction

In procedural texture generation , that I've already faced here and in which I get involved here  , can become useful to have a tool to manage Color Gradients. Searching the web I didn't find a c# control to implement what I needed. I decide to do it my self.

Background

I faced two cases where may become usefully color control gradient, first is in the gdi+ .net library (here)  , the second in texture generation. I the second case you start with a noise function to generate a heightmap, than you may want to associate a height value to a color; here come in hand a color gradient.

Let's suppose we generate the following noise:

applying a color gradient like this:  

we get the following (landscape-like) bitmap:

applying a different color gradient from the same starting noise we can get a (sky) bitmap like this:

Using the code

Using the control in design

To add the control ColGradCtr at design drag it into your form and size it like you want. It contains two default colors White (starting) and Black (ending).

Then you can reset the two starting colors in the load event of the contol (or in the load event of the form). At the same time you can add others colors.

        private void colGradCtr1_Load_1(object sender, EventArgs e)
        {
            colGradCtr1.reset(Color.Blue, Color.White); //redefine start and end color
            colGradCtr1.addColor(Color.FromArgb(0, 128, 128), 0.06f); //put a color in position 0.06
            colGradCtr1.addColor(Color.FromArgb(0, 0, 159), 0.60f);
            colGradCtr1.addColor(Color.FromArgb(6, 20, 203), 0.70f); 
            colGradCtr1.addColor(Color.FromArgb(146, 96, 53), 0.75f);
            colGradCtr1.addColor(Color.FromArgb(0, 100, 0), 0.80f);
            colGradCtr1.addColor(Color.FromArgb(64, 0, 0), 0.90f);
        }

The control need at leaast two colors (start and ending) that are respectively in position 0 and 1. All the other colors are in position >0 and <1.

Getting a sample color from ColGradCtr. If you give a float input >=0 and <=1 you get the corrisponding color.

Let's see the landscape generation routine:

//paints Picturebox pct according to heightmap and ColGradCtr col
private void reColor(PictureBox pct, ColGradCtr col){
            Bitmap b2 = new Bitmap(pct.Width, pct.Height);
            for (int i = 0; i < pct.Width; i++)
                for (int j = 0; j < pct.Height; j++)
                {
                    b2.SetPixel(i, j, col.getColor(heightMap[i, j]));                    
                }
            pct.Image = b2;
}

where heightMap is a float matrix containing the samples (heights) between 0 and 1.

The gdi+ aproach. If you ned a linear gradient you can get it fom ColGradCtr  in this manner : 

LinearGradientBrush br = new LinearGradientBrush(this.pictureBox1.ClientRectangle, Color.Black
, Color.Black,LinearGradientMode.BackwardDiagonal);
ColorBlend cb = BackGradCtr.getColorBlend();//here i get the blend from ctrl
br.InterpolationColors = cb;

offScreenDC.FillRectangle(br, this.pictureBox1.ClientRectangle);

Using the control at runtime. Pressing left mouse on a handle, you can move it, changing the color position. If you drag the handle out to the of control (to the right), you erase that color. Pressing right mouse near an handle let you modify the color value, pressing right mouse in empty place let you add a new color. Start and end colors can not be moved or erased, but you can change them.

The event management : I implemented two events , ColorChanged and ColorChanging. The first fires when you are moving a color , the second when you release mouse buttons and commit a change (modify a color, add a color , erase a color). Follows as I used ColorChanged event in thr example aplication:

private void colGradCtr1_ColorChanged(object sender, EventArgs e)
{
    reColor(pictureBox2, colGradCtr1);
}

The example application

Click "generate new noise" to test the gradients with a new noise.

Click gdi+ example to get the second example form: 

Points of Interest

ColGradCtr is not a "wrapper" of gdi+ ColrBlend  , its a "wrapper" of the class 

class Wgrad<T>

as I created it; its a "ordered" list of objects 

public class gradObj<T>
{
    public T ele { get; set; }
    public float w {get;set;}
    public gradObj(T e, float p)
    {
        ele = e;
        //clamp
        if (p > 1f)
            p = 1f;
        if (p < 0f)
            p = 0f;
        w = p;
    }
}

where T in our case is Color, and w is the position in the 0..1 scale.

Follows an explanation of the data structure behind the color gradient:

The class Wgrad<T> manages a List of obects T (in this case Color) mantaining them ordered depending on a float value that ranges between 0 and 1.

Some methods of Wgrad<T>:

public void <code>addEle</code>

Finaly the noiseGen is the class i developed to manage noise functions. It contains a c# implementation of 2d Perlin Noise.

History

Added Wgrad<T> explanation.

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here