For best control I suggest using a color calculation function.
There are many out there; here is one I use:
Color HsvToRgb(double h, double S, double V)
{
/// Convert HSV to RGB
/// h is from 0d - 360d
/// s,v values are 0d - 1d
/// r,g,b values are 0 - 255
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
double f = hue / 60 - Math.Floor(hue / 60);
value = value * 255;
int v = Convert.ToInt32(value);
int p = Convert.ToInt32(value * (1 - saturation));
int q = Convert.ToInt32(value * (1 - f * saturation));
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
if (hi == 0) return Color.FromArgb(255, v, t, p);
else if (hi == 1) return Color.FromArgb(255, q, v, p);
else if (hi == 2) return Color.FromArgb(255, p, v, t);
else if (hi == 3) return Color.FromArgb(255, p, q, v);
else if (hi == 4) return Color.FromArgb(255, t, p, v);
else return Color.FromArgb(255, v, p, q);
}
Do note the input ranges!!
Now it is easy to setup a Color
array at class level:
int width = 10;
int height = 9;
Color[,] colors;
And fill it:
void loadColors()
{
colors = new Color[width, height];
// load greys
for (int i = 0; i < width; i++ ) colors[i, 0] = HsvToRgb(0f, 0f, 1f * i / width);
// load bright stripe:
for (int i = 0; i < width; i++) colors[i, 1] = HsvToRgb(i* 360f / width, 0.33f, 1f);
// load matrix:
for (int j = 2; j < height; j++)
for (int i = 0; i < width; i++)
colors[i, j] = HsvToRgb(i * 360f / width, 1f, 1f * (height - j + 2) / height);
}
From this is is a snap to set the BackColors
of your Panels
.
Here is a Form.Paint
function, I used to create the above screenshot:
private void Form1_Paint(object sender, PaintEventArgs e)
{
int w = ClientSize.Width / width;
int h = ClientSize.Height / height;
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
using (SolidBrush brush = new SolidBrush(colors[i,j]))
e.Graphics.FillRectangle(brush, i * w, j * h, w, h);
}
}
Of course it is as simple as changing two numbers to make a finer grid, here 20x20:
Also note how the even spacing of hues doesn't really work well, as neither the human eye nor our common display systems are equally sensitive to changes in hues across the spectrum..
The eye is actually rather sensitive to greenish hues
the just-noticeable difference in wavelength varies from about 1 nm in
the blue-green and yellow wavelengths, to 10 nm and more in the longer
red and shorter blue wavelengths
but our monitors do a pretty bad job at creating different green hues..
Using an adapted list of perceptionally evenly spaced hues might help, depending on what you want..
Using this one-liner:
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
int hue = (int) ((Bitmap)pictureBox1.Image).GetPixel(e.X, e.Y).GetHue();
}
on the image above gives us one such list of hues:
20 32 41 50 58 72 133 163 170 177 183 190 197 206 269 288 307 324 334 346
I have modified it a little, maybe to make it work better with my monitor:
List<int> hues = new List<int>
{ 20, 32, 41, 50, 58, 72, 133, 162, 180, 188, 195, 205, 215, 223, 246, 267, 288, 300, 320, 346 };
And changing the above code (keeping width = 20) to
HsvToRgb(hues[i],..
results in this:
Update: I have replaced the HsvToRgb
function by a greatly simplified one.