c# finding similar colors

后端 未结 6 801
滥情空心
滥情空心 2021-01-05 16:39

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,

相关标签:
6条回答
  • 2021-01-05 17:08

    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);
    }
    
    0 讨论(0)
  • 2021-01-05 17:10

    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;
    }
    
    0 讨论(0)
  • 2021-01-05 17:11

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-05 17:17

    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.

    0 讨论(0)
  • 2021-01-05 17:24

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-05 17:28

    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.

    0 讨论(0)
提交回复
热议问题