petko_stankoski
petko_stankoski

Reputation: 10713

c# finding similar colors

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, for example AntiqueWhite and Bisque. Here's the color palette.

Bitmap LogoImg = new Bitmap("file1.jpeg");//the extension can be some other
System.Drawing.Color x = LogoImg.GetPixel(LogoImg.Width-1, LogoImg.Height-1);
LogoImg.MakeTransparent(x);
image1.Source = GetBitmapSource(LogoImg);

Upvotes: 8

Views: 13636

Answers (6)

NielW
NielW

Reputation: 3764

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;
}

Upvotes: 1

Jonas Elfstr&#246;m
Jonas Elfstr&#246;m

Reputation: 31428

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);
}

Upvotes: 3

Oliver
Oliver

Reputation: 45101

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.

Upvotes: 2

Soner G&#246;n&#252;l
Soner G&#246;n&#252;l

Reputation: 98750

Analyze this example Find the Nearest Color with C#. Hope gives you an idea.

enter image description 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);
    // 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;
    }
}

Upvotes: 2

Marco
Marco

Reputation: 57573

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;
    }
}

Upvotes: 7

Kevin Holditch
Kevin Holditch

Reputation: 5303

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.

Upvotes: 16

Related Questions