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

Color Picker

0.00/5 (No votes)
9 May 2006 1  
A nice color picker controls collection.

Sample Image - ColorPicker.jpg

Introduction

Any big framework's handicap is a low number of visual controls. Luckily the most useful are very often present, but sometimes we find some problems with the less common controls. Some days ago, I made a program that translates colors in HTML code. I first used three trackbars to change the red, green, and blue values. Later, I needed to put a more quick and intuitive solution, so I build this ColorPicker control. This control allows to select a color faster than using the previous method. Because I haven't seen a similar control in this site, I decided to post it here. In a recent update, I added a number of new controls. All the available controls are listed below:

ColorPickers (namespace Fuliggine.ColorPickers)
StableColorPicker Is a circular color picker that allows to select a single color.
SquareColorPicker Is a control that, given a base color, shows and allows to select its tones.
ColorBar Is a control that shows and allow to select all base colors derived from an RGB, except white and black.
FullColorBar Is a control that shows and allows to select all base colors derived from an RGB (also white and black).
ColorViewers (namespace Fuliggine.ColorPickers)
MonoFrameColor Is a control with a frame that shows the selected color.
DoubleFrameColor Is a control with two frames that show the two selected colors.
ColorGradient Is a control that shows all tones of a given color.
Special Pointers (namespace Fuliggine.ColorPickers)
HolePointer Is the pointer that selects the color in the controls.

The ColorPicker Controls

For ColorBar and FullColorBar controls, I divide the width in sections to allow all the possible combinations of R, G, B. After that, I find the step of color done in every pixel and draw the control line by line...

protected override void OnPaint(PaintEventArgs e)
{
    int R=255;
   int G=0;
   int B=0;
   //orizzontal...
   int colorstep=255/ ( this.Width/6 );
   int i=0;
   //the color step x pixel
   
    for(B=0;B<256;B+=colorstep ,i++)
    {
        e.Graphics.DrawLine(new Pen(new SolidBrush(
                   Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
    }
    B=255;
    for(R=255;R>0;R-=colorstep,i++)
    {
        e.Graphics.DrawLine(new Pen(new SolidBrush(
                   Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
    }
    R=0;
    for(G=0;G<256;G+=colorstep,i++)
    {
        e.Graphics.DrawLine(new Pen(new SolidBrush(
                   Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
    }
    G=255;
  
    for(B=255;B>0;B-=colorstep,i++)
    { 
        e.Graphics.DrawLine(new Pen(new SolidBrush(
                   Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
    }
    
    B=0;

    for(R=0;R<256;R+=colorstep,i++)
    {
        e.Graphics.DrawLine(new Pen(new SolidBrush(
                   Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
    }
    R=255;
    B=0;
    for(G=255;G>0;G-=colorstep,i++)
    {
        e.Graphics.DrawLine(new Pen(new SolidBrush(
                   Color.FromArgb(R,G,B)),1),i,0,i,this.Height);
    }
}

A similar way is used in ColorGradient and SquareColorPicker, but only the tones of the color are shown there.

protected override void OnPaint(PaintEventArgs e)
{
    int ScaleY=255/this.Height;

       for ( int y = 0 ; y<this.Height;y++)
    {
           int r=pColor.R-(y*ScaleY);
           if(r<0)
           {
               r=0;
           }
                          
           int g=pColor.G-(y*ScaleY);
           if(g<0)
           {
               g=0;
           }
                          
           int b=pColor.B-(y*ScaleY);
           if(b<0)
           {
               b=0;
           }
           e.Graphics.DrawLine(new Pen(new SolidBrush(
                      Color.FromArgb(r,g,b)),1),0,y,this.Width,y);
    }
}

The mono and double frame colors are realized by simple panels. The HolePointer is a simple control that bring itself in the parent bounds when the mouse drags it. Based on its position, controls will decide what the selected color is.

The Color Picker Application

The demo is a nice application, and simple but useful for those who use HTML. The application shows a way to use the StableColorPicker.

Sample Image - ColorPicker.jpg

How to Find the RGB Color

I decided to do a round rainbow. The main problem was that in an RGB system, we have three variables, and in a plain, there are only two. So I decided to take the x value as Red, Y value as Green, and the distance from the center as Blue. The circle is inscribed in a square of 255 pixels for each side. The distance from the center is calculated with Pythagoras's Theorem and resized to fit in the range 0-255. So at every point is associated a value between 0 and 255.

How to Paint the Circle

To paint the circle, I have two methods: the first one is to paint all the points on the ray, for each angle; the second one is to paint every point in a circle. The method to use can be selected by the user. The code is shown here:

protected override void OnPaint(PaintEventArgs e)
{
    //set some usefull var
    
    int offsett= 1;
    int width=this.ClientRectangle.Width-2;
    int height=this.ClientRectangle.Height-2;
    int rx= width/2;
    int x=10;
    int y=10;
    int cx=offsett+rx;
    double teta=0 ;            
    //refresh the background
    e .Graphics.FillRectangle(new SolidBrush(this.BackColor),
                              this.ClientRectangle);

    //The core of painting
    if ( AnimationRadial==true)
    {
        for (  teta = 0 ; teta <2*Math.PI; teta=teta + 0.003)
        {
            for ( double ray = 0 ; ray<rx ;ray= ray+1)
            {
                   x= cx+ Convert.ToInt32(ray* Math.Cos(teta));
                y= cx - Convert.ToInt32(ray* Math.Sin(teta));
                Rectangle rect= new Rectangle(x,y,1,1);

                e.Graphics.FillRectangle(new SolidBrush(
                           Color.FromArgb(x,y,(int)(ray/rx*255))),rect);
            }
        }
    }
    else
    {
        for ( double ray = 0 ; ray<rx ;ray= ray+1)
        {
            for (  teta = 0 ; teta <2*Math.PI; teta=teta + 0.003)
            {            
                   x= cx+ Convert.ToInt32(ray* Math.Cos(teta));
                y= cx - Convert.ToInt32(ray* Math.Sin(teta));
                Rectangle rect= new Rectangle(x,y,1,1);
                e.Graphics.FillRectangle(new SolidBrush(
                           Color.FromArgb(x,y,(int)(ray/rx*255))),rect);
            }
        }
    }
}

protected override void OnPaint(PaintEventArgs e)
{
    //set some usefull var
    int offsett= 1;
    int width=this.ClientRectangle.Width-2;
    int height=this.ClientRectangle.Height-2;
    int rx= width/2;
    int x=10;
    int y=10;
    int cx=offsett+rx;
    double teta=0 ;
    //refresh the background
    e.Graphics.FillRectangle(new SolidBrush(this.BackColor), 
                             this.ClientRectangle);

    //The core of painting
    if ( AnimationRadial==true)
    {
        for (  teta = 0 ; teta <2*Math.PI; teta=teta + 0.003)
        {
            for ( double ray = 0 ; ray<rx ;ray= ray+1)
            {    
                   x= cx+ Convert.ToInt32(ray* Math.Cos(teta));
                y= cx - Convert.ToInt32(ray* Math.Sin(teta));
                Rectangle rect= new Rectangle(x,y,1,1);

                e.Graphics.FillRectangle(new SolidBrush(
                           Color.FromArgb(x,y,(int)(ray/rx*255))),rect);
           
            }
        }
    }
    else
    {
        for ( double ray = 0 ; ray<rx ;ray= ray+1)
        {
            for (  teta = 0 ; teta <2*Math.PI; teta=teta + 0.003)
            {
                x= cx+ Convert.ToInt32(ray* Math.Cos(teta));
                y= cx - Convert.ToInt32(ray* Math.Sin(teta));
                Rectangle rect= new Rectangle(x,y,1,1);
                e.Graphics.FillRectangle(new SolidBrush(
                           Color.FromArgb(x,y,(int)(ray/rx*255))),rect);
            }
        }
    }
}

How to Select a Color

To select a color, I made a special class that can be moved by the user. Every color picture has one of this and the control returns the color under it.

Problems

A big problem is the flicker in repainting. I took the screenshot of the control and put it on a new control derived from PaintBox. This isn't an elegant solution, but works... I call this new control StableColorPicker.

Classes

In this release, there is the first version of the control (ColorPicker) which works fine but isn't very stable, and the second stable version (StableColorPicker).

Credits

This is only one of the possible solutions. Maybe this isn't the good, but I think that it's simple and fast. For advice, questions, or problems, please contact me.

If you would like to see my other works, please visit my home page: http://zeppaman.altervista.org.

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