Fill a panel with a gradient in three colors.

I am working on a project and I have to make a color picker look using C #.

So, I decided that it would be a panel with this background in a Win Forms application.

The background should have a gradient with three colors in rgb: red (0 - 255), blue (0 - 255) and green = 0.

gu0oJ.png

But I can not find any information about what I should use for this.

I tried to write code, and here is what I did.

{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { panel1.Paint += new PaintEventHandler(panel1_Paint); panel1.Refresh(); } private void panel1_Paint(object sender, PaintEventArgs e) { Point startPoint = new Point(0, 0); Point endPoint = new Point(150, 150); LinearGradientBrush lgb = new LinearGradientBrush(startPoint, endPoint, Color.FromArgb(255, 255, 0, 0), Color.FromArgb(255, 255, 255, 0)); Graphics g = e.Graphics; g.FillRectangle(lgb, 0, 0, 150, 150); // g.DrawLine(new Pen(Color.Yellow, 1.5f), startPoint, endPoint); } } 

}

And now I have a panel with this gradient

ORnzf.png

What should I use to get the gradient on the first image?

And the second question: what should I do to get the color of the pixel after clicking on this background?

+7
source share
2 answers

Here is an example of using the multicolor LinearGradientBrush in the Paint event:

 LinearGradientBrush linearGradientBrush = new LinearGradientBrush(panel4.ClientRectangle, Color.Red, Color.Yellow, 45); ColorBlend cblend = new ColorBlend(3); cblend.Colors = new Color[3] { Color.Red, Color.Yellow, Color.Green }; cblend.Positions = new float[3] { 0f, 0.5f, 1f }; linearGradientBrush.InterpolationColors = cblend; e.Graphics.FillRectangle(linearGradientBrush, panel4.ClientRectangle); 

enter image description here

You can freely vary the number of colors, the angle of inclination, or the spread of breakpoints. Just make sure you always have the same number of colors and breakpoints, and let them start at 0 and end at 1.

The colors in the constructor are ignored, by the way ..

To get the color, clicked on MouseClick , you can encode MouseClick :

 Color clickedColor = Color.Empty; private void panel_MouseClick(object sender, MouseEventArgs e) { using (Bitmap bmp = new Bitmap( panel.ClientSize.Width, panel4.ClientSize.Height)) { panel.DrawToBitmap(bmp,panel.ClientRectangle); clickedColor = bmp.GetPixel(eX, eY); } } 

If you want to catch a lot of clicks, it might be better to save Bitmap in a class level variable rather than creating its Bitmap . Setting it as the PanelImage background, as Kala's answer suggests, can also be a good option.

This should answer the question in the title. However, your first image does not show a gradient with three colors. It features a four-color 2D gradient. For such a more expensive coloring method, you have to put the colors in Bitmap and set it as Panel BackgroundImage .

** Update1 ** Here is a snippet of code that creates a 2D gradient:

 Bitmap Gradient2D(Rectangle r, Color c1, Color c2, Color c3, Color c4) { Bitmap bmp = new Bitmap(r.Width, r.Height); float delta12R = 1f * (c2.R - c1.R) / r.Height; float delta12G = 1f * (c2.G - c1.G) / r.Height; float delta12B = 1f * (c2.B - c1.B) / r.Height; float delta34R = 1f * (c4.R - c3.R) / r.Height; float delta34G = 1f * (c4.G - c3.G) / r.Height; float delta34B = 1f * (c4.B - c3.B) / r.Height; using (Graphics G = Graphics.FromImage(bmp) ) for (int y = 0; y < r.Height; y++) { Color c12 = Color.FromArgb(255, c1.R + (int)(y * delta12R), c1.G + (int)(y * delta12G), c1.B + (int)(y * delta12B)); Color c34 = Color.FromArgb(255, c3.R + (int)(y * delta34R), c3.G + (int)(y * delta34G), c3.B + (int)(y * delta34B)); using ( LinearGradientBrush lgBrush = new LinearGradientBrush( new Rectangle(0,y,r.Width,1), c12, c34, 0f) ) { G.FillRectangle(lgBrush, 0, y, r.Width, 1); } } return bmp; } 

Here is how you use it:

  public Form1() { InitializeComponent(); panel.BackgroundImage = Gradient2D(panel.ClientRectangle, Color.Black, Color.FromArgb(255, 0, 255, 0), Color.Red, Color.Yellow); } 

In this case, simple LinearGradientBrushes without a list of additional colors descending along the Panel height.

Note that Color.Green is a pretty darker shade, so I used FromRgb for a brighter green. If your Panel larger than 256 pixels, you can optimize it by filling in large stripes; if it's vertical, you can change the loop so that it goes through x instead of y ..

Here is the result:

enter image description here

To select with one click, just read the color from BackgroundImage :

 private void panel_MouseClick(object sender, MouseEventArgs e) { clickedColor = ((Bitmap)panel.BackgroundImage).GetPixel(eX, eY); } 

Update 2:

Looking through this MSDN page, we find that there is actually a built-in tool for creating 2D gradients.

This is PathGradientBrush

Here is an example ..:

enter image description here

.. and code:

 Bitmap Gradient2D(Rectangle r, Color c1, Color c2, Color c3, Color c4) { List<Color> colors = new List<Color> { c1, c3, c4, c2 }; Bitmap bmp = new Bitmap(r.Width, r.Height); using (Graphics g = Graphics.FromImage(bmp)) for (int y = 0; y < r.Height; y++) { using (PathGradientBrush pgb = new PathGradientBrush(getCorners(r).ToArray())) { pgb.CenterColor = medianColor(colors); pgb.SurroundColors = colors.ToArray(); g.FillRectangle(pgb, 0, y, r.Width, 1); } } return bmp; } 

This uses two simple helper functions. One returns the corner points of the rectangle:

 public List<PointF> getCorners(RectangleF r) { return new List<PointF>() { r.Location, new PointF(r.Right, r.Top), new PointF(r.Right, r.Bottom), new PointF(r.Left, r.Bottom)}; } 

Another calculates the median color from the List<Color> . This is used as CenterColor ..:

 public static Color medianColor(List<Color> cols) { int c = cols.Count; return Color.FromArgb(cols.Sum(x => xA) / c, cols.Sum(x => xR) / c, cols.Sum(x => xG) / c, cols.Sum(x => xB) / c); } 

The result is pretty much the same as using the LinearGradientBrushes stripes. It is simpler and should work a little better; this is what I would recommend, obviously ..

Pay attention to the changed order of colors (or corners)! SurroundColors apply to opposite corners of a rectangle.

Remarks:

By studying this page, you may find that there are actually four different uses of this brush.

They differ in how to configure it ( GraphicsPath or Point[] ), which color collections to fill in ( SurroundColors or InterpolationColors.Colors ), and how to call them (using a shape or path). And the results are also very different.

Also note that only three results or four paths are shown, although code is provided for all four! ..

+15
source

From the argument e of the mouse click event, you can get the Point with the exact coordinates of the click:

 Point clickPoint = e.GetPosition(backgroundControlWithImg); 

Then get the color of the image at this position using something like:

 System.Drawing.Image image = backgroundControl.BackgroundImage; Bitmap _bitmap = new Bitmap(image); Color _color = bitmap.GetPixel(Point.x, Point.y); 

Something like that. What do you use for color picker, or WPF?

+2
source

All Articles