Convert System.Drawing.Color to RGB and Hex Value

189,563

Solution 1

I'm failing to see the problem here. The code looks good to me.

The only thing I can think of is that the try/catch blocks are redundant -- Color is a struct and R, G, and B are bytes, so c can't be null and c.R.ToString(), c.G.ToString(), and c.B.ToString() can't actually fail (the only way I can see them failing is with a NullReferenceException, and none of them can actually be null).

You could clean the whole thing up using the following:

private static String HexConverter(System.Drawing.Color c)
{
    return "#" + c.R.ToString("X2") + c.G.ToString("X2") + c.B.ToString("X2");
}

private static String RGBConverter(System.Drawing.Color c)
{
    return "RGB(" + c.R.ToString() + "," + c.G.ToString() + "," + c.B.ToString() + ")";
}

Solution 2

You could keep it simple and use the native color translator:

Color red = ColorTranslator.FromHtml("#FF0000");
string redHex = ColorTranslator.ToHtml(red);

Then break the three color pairs into integer form:

int value = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);

Solution 3

If you can use C#6 or higher, you can benefit from Interpolated Strings and rewrite @Ari Roth's solution like this:

C# 6:

public static class ColorConverterExtensions
{
    public static string ToHexString(this Color c) => $"#{c.R:X2}{c.G:X2}{c.B:X2}";

    public static string ToRgbString(this Color c) => $"RGB({c.R}, {c.G}, {c.B})";
}

Also:

  • I add the keyword this to use them as extensions methods.
  • We can use the type keyword string instead of the class name.
  • We can use lambda syntax.
  • I rename them to be more explicit for my taste.

Edit: If you want to support the alpha channel:

public static class ColorConverterExtensions
{

    // #RRGGBB
    public static string ToHexString(this Color c) => $"#{c.R:X2}{c.G:X2}{c.B:X2}";

    // RGB(R, G, B)
    public static string ToRgbString(this Color c) => $"RGB({c.R}, {c.G}, {c.B})";

    // #RRGGBBAA
    public static string ToHexaString(this Color c) => $"#{c.R:X2}{c.G:X2}{c.B:X2}{c.A:X2}";

    public static double ToProportion(byte b) => b / (double)Byte.MaxValue;

    // RGBA(R, G, B, A)
    public static string ToRgbaString(this Color c) => $"RGBA({c.R}, {c.G}, {c.B}, {ToProportion(c.A):N2})";
}

Fun fact: I have to search about the proportion name, because we want for a value in the interval [0, 1] not a percent which is in the interval [0, 100]

Solution 4

e.g.

 ColorTranslator.ToHtml(Color.FromArgb(Color.Tomato.ToArgb()))

This can avoid the KnownColor trick.

Solution 5

For hexadecimal code try this

  1. Get ARGB (Alpha, Red, Green, Blue) representation for the color
  2. Filter out Alpha channel: & 0x00FFFFFF
  3. Format out the value (as hexadecimal "X6" for hex)

For RGB one

  1. Just format out Red, Green, Blue values

Implementation

private static string HexConverter(Color c) {
  return String.Format("#{0:X6}", c.ToArgb() & 0x00FFFFFF);
}

public static string RgbConverter(Color c) {
  return String.Format("RGB({0},{1},{2})", c.R, c.G, c.B);
}
Share:
189,563
Nazmul
Author by

Nazmul

When studying Mechanical Engineering, I had a course on FORTRAN and that basically inspire me to dive into field of Programming language. Signed in Stackoverflow almost 11 years ago and so far tried to help others and as well as receive awesome helps from other users. Born in Bangladesh and currently living in Canada. Like Bangladeshi curry and Japanese sushi.

Updated on July 08, 2022

Comments

  • Nazmul
    Nazmul almost 2 years

    Using C# I was trying to develop the following two. The way I am doing it may have some problem and need your kind advice. In addition, I dont know whether there is any existing method to do the same.

    private static String HexConverter(System.Drawing.Color c)
    {
        String rtn = String.Empty;
        try
        {
            rtn = "#" + c.R.ToString("X2") + c.G.ToString("X2") + c.B.ToString("X2");
        }
        catch (Exception ex)
        {
            //doing nothing
        }
    
        return rtn;
    }
    
    private static String RGBConverter(System.Drawing.Color c)
    {
        String rtn = String.Empty;
        try
        {
            rtn = "RGB(" + c.R.ToString() + "," + c.G.ToString() + "," + c.B.ToString() + ")";
        }
        catch (Exception ex)
        {
            //doing nothing
        }
    
        return rtn;
    }
    

    Thanks.

  • Nazmul
    Nazmul over 14 years
    But if I do this way, Color red = System.Drawing.Color.Red; string redHex = ColorTranslator.ToHtml(red); it does not provide the Hex Value.
  • Troy Hunt
    Troy Hunt over 14 years
    Certainly should do, I tested that code specifically and got #"FF0000". What are you getting? You might also like to refer to the MSDN reference: msdn.microsoft.com/en-us/library/…
  • Nazmul
    Nazmul over 14 years
    Try with Color red = System.Drawing.Color.Red; --> it does not provide #FF0000.
  • Troy Hunt
    Troy Hunt over 14 years
    So using exactly the first code block I provided, what is the value of redHex? I think something on your side is missing.
  • Nazmul
    Nazmul over 14 years
    The code you have provided works but when I change the first line of your code to : Color red = System.Drawing.Color.Red; --> Then it does not give the hex code. It gives "Red" as an output.
  • anon
    anon over 11 years
    @Hoque - Confirmed. ColorTranslator gives a "friendly" name to the color. How annoying!
  • JMD
    JMD about 10 years
    I'd go so far as to say that empty try-catch blocks should (almost) universally be eradicated. They have great potential to lead to buggy code, if not now then down the road when this code is modified. Still, +1 for the cleaned up code, and to the OP +1 for a well-framed question.
  • zacharydl
    zacharydl about 10 years
    Took me a while to find the VB equivelant: String.Format("#{0:X2}{1:X2}{2:X2}", c.R, c.G, c.B)
  • Brad
    Brad almost 10 years
    +1 bc this caused me to look at the .NET implementation of ColorTranslator which is the accepted answer + KnownColor logic. i didn't want that logic, so i went with the accepted answer (but made extension methods)
  • mike
    mike over 8 years
    This may not be suitable for some cases, because a quick test within a WinForm lead to the following result: System.Drawing.ColorTranslator.ToHtml(Me.BackColor) = "buttonface" instead of the (desired) hex value.
  • aloisdg
    aloisdg about 8 years
    I post an adaptation of your code to C#6 as an alternative answer. You can see it here.
  • Mohammed Noureldin
    Mohammed Noureldin over 6 years
    I belive it should be Hex2, not Hex, otherwise the color maybe wrong interpolated.
  • User1
    User1 over 6 years
    @MohammedNoureldin Where would Hex2 go in the code, I have seen colours being slightly different sometimes?
  • Mohammed Noureldin
    Mohammed Noureldin over 6 years
    I meant X2 instead of X, otherwise you might get 1 instead of 01 then it will be a problem.
  • LarryBud
    LarryBud over 5 years
    This will produce the wrong color if the color has an alpha channel (transparency). You will get full opaqueness.
  • Ari Roth
    Ari Roth about 5 years
    @LarryBud Absolutely true, and thank you for pointing it out. My example skipped the alpha channel only because I was keying off of the original question, which also didn't include it. :)
  • ProfK
    ProfK over 4 years
    @MohammedNoureldin Yeah, with X2 then you don't need all the color.B.ToString("X").Length == 1 ? ternaries.
  • Shockwaver
    Shockwaver about 4 years
    So clean... +1!
  • George Fabish
    George Fabish over 2 years
    To make this work with web browsers I had to switch the formatting so that the alpha parameter would be added last.