I want to call a method with argument color. But there are a lot of colors which differ only by a shade. How can I find the colors which differ from my color only by little,
You can get the closest color from the KnownColors enum.
// A color very close to Rosy Brown
var color = Color.FromArgb(188, 143, 142);
var colors = Enum.GetValues(typeof (KnownColor))
.Cast<KnownColor>()
.Select(Color.FromKnownColor);
var closest = colors.Aggregate(Color.Black,
(accu, curr) =>
ColorDiff(color, curr) < ColorDiff(color, accu) ? curr : accu);
And the support method
private int ColorDiff(Color color, Color curr)
{
return Math.Abs(color.R - curr.R) + Math.Abs(color.G - curr.G) + Math.Abs(color.B - curr.B);
}
I used Keven Holditch's answer below. But I modified it for my own purposes. This version uses exclusive-or so that only one value can be off by the tolerance and still return true. (Tolerance is also <= instead of just <.)
private bool AreColorsSimilar(Color c1, Color c2, int tolerance)
{
return Math.Abs(c1.R - c2.R) <= tolerance ^
Math.Abs(c1.G - c2.G) <= tolerance ^
Math.Abs(c1.B - c2.B) <= tolerance;
}
I found this routine here:
Color nearest_color = Color.Empty;
foreach (object o in WebColors)
{
// compute the Euclidean distance between the two colors
// note, that the alpha-component is not used in this example
dbl_test_red = Math.Pow(Convert.ToDouble(((Color)o).R) - dbl_input_red, 2.0);
dbl_test_green = Math.Pow(Convert.ToDouble
(((Color)o).G) - dbl_input_green, 2.0);
dbl_test_blue = Math.Pow(Convert.ToDouble
(((Color)o).B) - dbl_input_blue, 2.0);
temp = Math.Sqrt(dbl_test_blue + dbl_test_green + dbl_test_red);
// explore the result and store the nearest color
if(temp == 0.0)
{
nearest_color = (Color)o;
break;
}
else if (temp < distance)
{
distance = temp;
nearest_color = (Color)o;
}
}
Could you use a method like this:
public bool AreColorsSimilar(Color c1, Color c2, int tolerance)
{
return Math.Abs(c1.R - c2.R) < tolerance &&
Math.Abs(c1.G - c2.G) < tolerance &&
Math.Abs(c1.B - c2.B) < tolerance;
}
This method takes two colours and a tolerance and returns whether those two colours are close or not based on their RGB values. I think that should do the trick but you may need to extend to include brightness and saturation.
Analyze this example Find the Nearest Color with C#. Hope gives you an idea.
Color nearest_color = Color.Empty;
foreach (object o in WebColors)
{
// compute the Euclidean distance between the two colors
// note, that the alpha-component is not used in this example
dbl_test_red = Math.Pow(Convert.ToDouble(((Color)o).R) - dbl_input_red, 2.0);
dbl_test_green = Math.Pow(Convert.ToDouble
(((Color)o).G) - dbl_input_green, 2.0);
dbl_test_blue = Math.Pow(Convert.ToDouble
(((Color)o).B) - dbl_input_blue, 2.0);
// it is not necessary to compute the square root
// it should be sufficient to use:
// temp = dbl_test_blue + dbl_test_green + dbl_test_red;
// if you plan to do so, the distance should be initialized by 250000.0
temp = Math.Sqrt(dbl_test_blue + dbl_test_green + dbl_test_red);
// explore the result and store the nearest color
if(temp == 0.0)
{
// the lowest possible distance is - of course - zero
// so I can break the loop (thanks to Willie Deutschmann)
// here I could return the input_color itself
// but in this example I am using a list with named colors
// and I want to return the Name-property too
nearest_color = (Color)o;
break;
}
else if (temp < distance)
{
distance = temp;
nearest_color = (Color)o;
}
}
I think to find similar colors you should take a look at the HSL or HSB color space instead of the RGB one, cause with this it is a lot easier to find similar colors.
Within .Net you can call the GetHue(), GetSaturation() and GetBrightness() method to get these values from a given color and compare these values to find similar ones.
If you need the way back from an HSB value to a color you can also use this method.