3

I have color coming in the below way

{ Name=ffff8c00, ARGB=(255, 255, 140, 0) }

can i chekc the color name? Whether it is red or green..i wanted the name of color..

Is it possible to find ?

leppie
  • 115,091
  • 17
  • 196
  • 297
Pankaj
  • 9,749
  • 32
  • 139
  • 283
  • 1
    If the name is known, it can be retrieved from `Name` property. Otherwise you cannot get the name in any simple way. – Alex Skalozub Apr 01 '14 at 02:55
  • You could create a `HashMap` mapping hex color values to names using the data from http://cloford.com/resources/colours/namedcol.htm, then retrieve the name (if one is available) from your map based on the numeric value of the color – Sam Apr 01 '14 at 02:59

2 Answers2

8

You can get the name from KnownColor. Try like below

        string name = "Unknown";
        foreach (KnownColor kc in Enum.GetValues(typeof(KnownColor)))
        {
            Color known = Color.FromKnownColor(kc);
            if (Color.FromArgb(255,255,140,0).ToArgb() == known.ToArgb())
            {
                label1.Text = known.Name;
                break;
            }
        }

Here I just hard code your value and return the name in label named 'label1'.

Check this thread http://social.msdn.microsoft.com/Forums/vstudio/en-US/3c80583e-d0a9-45e9-842a-bd7258f1fd2f/get-color-name-in-c?forum=csharpgeneral

Akhil
  • 1,918
  • 5
  • 30
  • 74
3

While it is true you can use the Name property to get the name of the color, this is only true if a name was provided while constructing the Color object or if the Color object was retrieved using a KnownColor name. If constructed using custom ARGB values, these methods will not work, even if values matching a known color are provided. You can create a static Dictionary using the information from a source (I got my values from here) that you trust for color names, and provide a list of possibilities.

By coming up with a simple definition of the distance between two colors as the absolute value of the difference between the individual color components, we can expand the idea to retrieve the name for the color "closest" to the provided color. Note that I use the MinBy extension method provided by the MoreLINQ project as suggested in this SO answer to keep track of my objects more easily.

public class ColorMapper {

    //create the dictionary with the elements you are interested in
    private static Dictionary<int, String> colorMap = new Dictionary<int, String>()
    {
        {0xFFB6C1, "Light Pink"},
        {0x6B8E23, "Olive Drab"},
        //and the list goes on
    };

    public static String GetName(Color color)
    {
        //mask out the alpha channel
        int myRgb = (int)(color.ToArgb() & 0x00FFFFFF);
        if (colorMap.ContainsKey(myRgb))
        {
            return colorMap[myRgb];
        }
        return null;
    }
    public static String GetNearestName(Color color)
    {
        //check first for an exact match
        String name = GetName(color);
        if (color != null) 
        {
            return name;
        } 
        //mask out the alpha channel
        int myRgb = (int)(color.ToArgb() & 0x00FFFFFF);
        //retrieve the color from the dictionary with the closest measure
        int closestColor = colorMap.Keys.Select(colorKey => new ColorDistance(colorKey, myRgb)).MinBy(d => d.distance).colorKey;
        //return the name
        return colorMap[closestColor];
    }
}

//Just a simple utility class to store our
//color values and the distance from the color of interest
public class ColorDistance
{
    private int _colorKey;
    public int colorKey
    {
        get { return _colorKey; }
    }
    private int _distance;
    public int distance 
    {
        get {return _distance;}
    }

    public ColorDistance(int colorKeyRgb, int rgb2)
    {
        //store for use at end of query
        this._colorKey = colorKeyRgb;

        //we just pull the individual color components out
        byte r1 = (byte)((colorKeyRgb >> 16) & 0xff);
        byte g1 = (byte)((colorKeyRgb >> 8) & 0xff);
        byte b1 = (byte)((colorKeyRgb) & 0xff);

        byte r2 = (byte)((rgb2 >> 16) & 0xff);
        byte g2 = (byte)((rgb2 >> 8) & 0xff);
        byte b2 = (byte)((rgb2) & 0xff);

        //provide a simple distance measure between colors
        _distance = Math.Abs(r1 - r2) + Math.Abs(g1 - g2) + Math.Abs(b1 - b2);
    }
}

Edit: Using the suggestion from Scott, you can initialize your color value names using the KnownColor enumeration to list all of your values. You can just add the static constructor as follows to the ColorMapper class and remove our initialization elements from the Dictionary declaration.

static ColorMapper()
{
    foreach (KnownColor kc in Enum.GetValues(typeof(KnownColor)))
    {
        if (!ignoredColors.Contains(kc))
        {
            Color c = Color.FromKnownColor(kc);
            try
            {
                colorMap.Add(c.ToArgb() & 0x00FFFFFF, c.Name);
            }
            //duplicate colors cause an exception
            catch { }
        }
    }
}

You will notice that I check for ignoredColors. This is because the KnownColors enumeration contains values for colors not likely of interest to you. Specifically, the system-defined colors for UI colors probably don't interest you. ignoredColors is just a HashSet<KnownColor> containing the elements such as KnownColor.ActiveCaptionText, KnownColor.ButtonFace and the like.

You could also add the static keyword to the ColorMapper class declaration

public static class ColorMapper
{
    ...
}

and change the method signatures to:

public static String GetName(this Color color);
public static String GetNearestName(this Color color);

to convert the methods to Extension Methods. This makes getting the name as easy as:

Color myColor = Color.FromArgb(255,0,0,0);//black
String myColorName = myColor.GetName();
String myNearestName = myColor.GetNearestName();
Community
  • 1
  • 1
Sam
  • 1,176
  • 6
  • 19
  • It might be better to use a [KeyedCollection](http://msdn.microsoft.com/en-us/library/ms132438%28v=vs.110%29.aspx) instead of a Dictionary and also populate the static list by enumerating though the color names enum. – Scott Chamberlain Apr 01 '14 at 06:19
  • @ScottChamberlain Thanks! Good point on the using the enum. I edited to reflect your suggestion. I'll leave the `KeyedCollection` alone for now, since I haven't heard about it before, but look forward to learning about a new part of the .NET framework. – Sam Apr 01 '14 at 14:03
  • The keyed collection is super simple, in fact I can put the entire code for it in this comment `class ColorDictionary : KeyedCollection { protected override int GetKeyForItem(Color color) { return color.ToArgb(); } }` It now behaves as a `Dictionary` but you only need to call it like `.Add(Color.White)` and it auto populates the key with `0xFFFFFFFF` based on the function you implemented in `TKey GetKeyForItem(TValue)`. The only other tweak I would suggest is write a custom comparer for your dictionary that compares to `Color` objects but ignores the Alpha channel. – Scott Chamberlain Apr 01 '14 at 14:07