将System.Drawing.Color转换为RGB和十六进制值

154

我使用 C# 尝试开发以下两个,但我目前的方法可能存在问题,需要您的指导。另外,我不知道是否有任何现有的方法可以实现相同的功能。

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;
}
感谢。

@Rod https://dev59.com/5WIi5IYBdhLWcg3w_QiG这段代码中的“ToString("X2")”是将数字转换为16进制字符串的方法。其中,“X2”表示输出的字符串应该是两个字符宽,不足两个字符时在前面补零。 - samgak
6个回答

254

我看不出这里存在问题。代码看起来很好。

唯一能想到的可能就是try/catch块是多余的——Color是一个结构体,RGB都是字节,因此 c 不能为null,并且c.R.ToString()c.G.ToString()c.B.ToString()实际上不会失败(我唯一能想到它们失败的方式是抛出NullReferenceException,而它们中的任何一个都不可能是null)。

您可以使用以下代码来简化整个过程:

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() + ")";
}

2
我甚至可以说在编程中空的 try-catch 块(几乎)普遍应该被消除。如果不是现在,那么这段代码修改后很有可能会导致错误。尽管如此,对于清理代码 +1,对于 OP 很好地提出问题 +1。 - JMD
11
我需要一些时间才能找到VB的等效写法:String.Format("#{0:X2}{1:X2}{2:X2}", c.R, c.G, c.B),意思是将RGB颜色代码格式化为十六进制字符串,并在前面加上 "#" 符号。 - zacharydl
2
我将您的代码改编成C#6版本,并作为另一种答案发布。您可以在此处查看它:https://dev59.com/2nE95IYBdhLWcg3wPbd7#37821008。 - aloisdg
如果颜色具有 alpha 通道(透明度),则此方法将产生错误的颜色。您将获得完全不透明的颜色。 - LarryBud
@LarryBud 完全正确,谢谢你指出来。我的例子之所以跳过了 alpha 通道,只是因为我参考了原始问题,而原始问题也没有包括它。 :) - Ari Roth
@LarryBud 这个答案支持 alpha 通道。 - aloisdg

218

您可以保持简单,使用本地颜色转换器:

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

然后将三个颜色对分别转换成整数形式:

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

9
如果我这样做, Color red = System.Drawing.Color.Red; string redHex = ColorTranslator.ToHtml(red);它没有提供十六进制值。 - Nazmul
9
您提供的代码有效,但当我将您的代码的第一行更改为:Color red = System.Drawing.Color.Red; --> 那么它不会给出十六进制代码。它会输出“Red”。 - Nazmul
5
确认,ColorTranslator为颜色提供了“友好”的名称。真烦人! - anon
这种方式可能不适用于某些情况,因为在 WinForm 内进行快速测试会得到以下结果:System.Drawing.ColorTranslator.ToHtml(Me.BackColor) = "buttonface" 而不是(所期望的)十六进制值。 - mike
还有一件需要注意的事情是,你的颜色中任何Alpha值都会丢失! - Crown
显示剩余4条评论

57

如果您可以使用C#6或更高版本,您可以受益于插值字符串,并像这样重新编写@Ari Roth的解决方案

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

此外:

  • 我添加关键字this来将它们用作扩展方法。
  • 我们可以使用类型关键字string而不是类名。
  • 我们可以使用Lambda语法。
  • 我将它们重命名以适应我的喜好更加明确。

编辑:如果您想支持Alpha通道:

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

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

有趣的事实: 我不得不搜索关于 "比例" 名称的内容,因为我们想要的是值在区间 [0, 1] 而不是百分比,在区间 [0, 100]


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

这可以避免 KnownColor 技巧。


3
我找到了一个很好用的扩展方法,它可以很好地工作。
public static string ToHex(this Color color)
{
    return String.Format("#{0}{1}{2}{3}"
        , color.A.ToString("X").Length == 1 ? String.Format("0{0}", color.A.ToString("X")) : color.A.ToString("X")
        , color.R.ToString("X").Length == 1 ? String.Format("0{0}", color.R.ToString("X")) : color.R.ToString("X")
        , color.G.ToString("X").Length == 1 ? String.Format("0{0}", color.G.ToString("X")) : color.G.ToString("X")
        , color.B.ToString("X").Length == 1 ? String.Format("0{0}", color.B.ToString("X")) : color.B.ToString("X"));
}

参考:https://social.msdn.microsoft.com/Forums/en-US/4c77ba6c-6659-4a46-920a-7261dd4a15d0/how-to-convert-rgba-value-into-its-equivalent-hex-code?forum=winappswithcsharp

本文涉及IT技术领域,介绍如何将RGBA值转换为相应的十六进制代码。在编写代码时,需要注意格式和语法,并且确保代码易于理解和维护。如果您遇到任何问题,请参考上述链接,或向专业人士寻求帮助。

我认为应该是Hex2,而不是Hex,否则颜色可能会被错误地插值。 - Mohammed Noureldin
@MohammedNoureldin 在代码中应该放置Hex2,有时我看到颜色略有不同。 - JKennedy
我是指 X2 而不是 X,否则你可能会得到 1 而不是 01,那就会有问题。 - Mohammed Noureldin
@MohammedNoureldin 是的,如果使用 X2,那么您就不需要所有的 color.B.ToString("X").Length == 1 ? 三元运算符了。 - ProfK
为了使其与Web浏览器配合使用,我不得不更改格式,以便将alpha参数添加到最后。 - George Fabish

3

对于十六进制代码,请尝试以下操作:

  1. 获取颜色的ARGB(Alpha、Red、Green、Blue)表示
  2. 过滤掉Alpha通道:& 0x00FFFFFF
  3. 将值格式化(使用十六进制“X6”格式)

对于RGB,只需将红色绿色蓝色值进行格式化

实现

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接