【问题标题】:How to convert RGBA css color format to hexadecimal format如何将 RGBA css 颜色格式转换为十六进制格式
【发布时间】:2016-11-24 09:23:42
【问题描述】:

在我的 selenium 代码中,我需要验证背景颜色代码是否为 #192856。但是当我得到那个元素的 CSS 属性时,它会给我 rgba 格式的颜色。现在我需要获取十六进制值本身的值。我该怎么做?

quickLinkstab.GetCssValue("background-color")

上面给出了“rgba(25,40,86,1)”的值,即 rgba 值。有什么办法可以将它转换回十六进制?或者我可以在 Hex 本身中获得价值?

我也试过下面的代码

 string colorcode = menuColor;
        int argb = Int32.Parse(colorcode.Replace("#", ""), NumberStyles.HexNumber);
        Color clr = Color.FromArgb(argb);


        int r = Convert.ToInt16(clr.R);
        int g = Convert.ToInt16(clr.G);
        int b = Convert.ToInt16(clr.B);
        int a = Convert.ToInt16(clr.A);
        string x = string.Format("rgba({0}, {1}, {2}, {3});", r, g, b,a);

但是这个给了我像 "rgba(25, 40, 86, 0);" 这样的价值. “a”值的差异。就像我的代码为“a”给了我 0 但 cssvalue 是 1。

我更倾向于直接获取十六进制值的解决方案,或者如果不可能,则将 rgba 转换为十六进制。

【问题讨论】:

标签: c# css selenium-webdriver colors


【解决方案1】:

以下代码涵盖十六进制格式、rgb格式和rgba格式。

public static class ColorHelper
{
    public static Color ParseColor(string cssColor)
    {
        cssColor = cssColor.Trim();

        if (cssColor.StartsWith("#"))
        {
            return ColorTranslator.FromHtml(cssColor);
        }
        else if (cssColor.StartsWith("rgb")) //rgb or argb
        {
            int left = cssColor.IndexOf('(');
            int right = cssColor.IndexOf(')');

            if (left < 0 || right < 0)
                throw new FormatException("rgba format error");
            string noBrackets = cssColor.Substring(left + 1, right - left - 1);

            string[] parts = noBrackets.Split(',');

            int r = int.Parse(parts[0], CultureInfo.InvariantCulture);
            int g = int.Parse(parts[1], CultureInfo.InvariantCulture);
            int b = int.Parse(parts[2], CultureInfo.InvariantCulture);

            if (parts.Length == 3)
            {
                return Color.FromArgb(r, g, b);
            }
            else if (parts.Length == 4)
            {
                float a = float.Parse(parts[3], CultureInfo.InvariantCulture);
                return Color.FromArgb((int)(a * 255), r, g, b);
            }
        }
        throw new FormatException("Not rgb, rgba or hexa color string");
    }
}

预期结果:

[TestClass]
public class ColorParserTest
{
    [TestMethod]
    public void TestParseColorRGB()
    {
        Color c = ColorHelper.ParseColor("rgb(110,120,130)");

        Assert.AreEqual(110, c.R);
        Assert.AreEqual(120, c.G);
        Assert.AreEqual(130, c.B);
        Assert.AreEqual(255, c.A);
    }

    [TestMethod]
    public void TestParseColorRGBA()
    {
        Color c = ColorHelper.ParseColor("rgba(110,120,130,0.5)");

        Assert.AreEqual(110, c.R);
        Assert.AreEqual(120, c.G);
        Assert.AreEqual(130, c.B);
        Assert.AreEqual(127, c.A);
    }

    [TestMethod]
    public void TestParseColorHexa()
    {
        Color c = ColorHelper.ParseColor("#192856");

        Assert.AreEqual(25, c.R);
        Assert.AreEqual(40, c.G);
        Assert.AreEqual(86, c.B);
        Assert.AreEqual(255, c.A);
    }
}

【讨论】:

  • 如何扩展代码以支持ColorHelper.ParseColor("#0000007F");
【解决方案2】:

使用 System.Drawing.ColorTranslator

string htmlColor = ColorTranslator.ToHtml(myColor);

使用字符串格式

//RGB
String.Format("#{0:X2}{1:X2}{2:X2}", colorValue.R,colorValue.G,colorValue.B);
//RGBA
String.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", colorValue.A,colorValue.R,colorValue.G,colorValue.B);

扩展

public static class ColorExtension
{
    public static string HexFormat(this Color colorValue)
    {
        return String.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", colorValue.A, colorValue.R, colorValue.G, colorValue.B);
    }
}

【讨论】:

  • 这也忽略了 alpha 通道(甚至是内置的 ColorTranslator 方法)
【解决方案3】:

我已经扩展了 Thomas 的答案以涵盖 #RGBA/#RRGGBBAA 格式。

您可能希望以不同的方式处理错误,如果无法解析输入,我更愿意只返回 Color.Empty。

(向 Typescript 添加单元测试导致查看一些 C# 代码,这导致发现 ColorTranslator 完全不知道 alpha 值 - 不要假设任何内容,测试所有内容!)

public static ColorUtils
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "ColorTranslator throws System.Exception")]
    public static Color HtmlToColor(string htmlColor)
    {
        Guard.ArgumentIsNotNull(htmlColor, nameof(htmlColor));

        var htmlLowerCase = htmlColor.ToLower().Trim();

        try
        {
            if (htmlLowerCase.StartsWith("rgb"))
            {
                return ArgbToColor(htmlLowerCase);
            }
            else if (htmlLowerCase.StartsWith("#"))
            {
                return HexToColor(htmlLowerCase);
            }
            else
            {
                // Fallback to ColorTranslator for named colors, e.g. "Black", "White" etc.
                return ColorTranslator.FromHtml(htmlLowerCase);
            }
        }
        catch
        {
            // ColorTranslator throws System.Exception, don't really care what the actual error is.
        }

        return Color.Empty;
    }

    private static Color HexToColor(string htmlLowerCase)
    {
        var len = htmlLowerCase.Length;

        // #RGB
        if (len == 4)
        {
            var r = Convert.ToInt32(htmlLowerCase.Substring(1, 1), 16);
            var g = Convert.ToInt32(htmlLowerCase.Substring(2, 1), 16);
            var b = Convert.ToInt32(htmlLowerCase.Substring(3, 1), 16);

            return Color.FromArgb(r + (r * 16), g + (g * 16), b + (b * 16));
        }

        // #RGBA
        else if (len == 5)
        {
            var r = Convert.ToInt32(htmlLowerCase.Substring(1, 1), 16);
            var g = Convert.ToInt32(htmlLowerCase.Substring(2, 1), 16);
            var b = Convert.ToInt32(htmlLowerCase.Substring(3, 1), 16);
            var a = Convert.ToInt32(htmlLowerCase.Substring(4, 1), 16);

            return Color.FromArgb(a + (a * 16), r + (r * 16), g + (g * 16), b + (b * 16));
        }

        // #RRGGBB
        else if (len == 7)
        {
            return Color.FromArgb(
                Convert.ToInt32(htmlLowerCase.Substring(1, 2), 16),
                Convert.ToInt32(htmlLowerCase.Substring(3, 2), 16),
                Convert.ToInt32(htmlLowerCase.Substring(5, 2), 16));
        }

        // #RRGGBBAA
        else if (len == 9)
        {
            return Color.FromArgb(
                Convert.ToInt32(htmlLowerCase.Substring(7, 2), 16),
                Convert.ToInt32(htmlLowerCase.Substring(1, 2), 16),
                Convert.ToInt32(htmlLowerCase.Substring(3, 2), 16),
                Convert.ToInt32(htmlLowerCase.Substring(5, 2), 16));
        }

        return Color.Empty;
    }

    private static Color ArgbToColor(string htmlLowerCase)
    {
        int left = htmlLowerCase.IndexOf('(');
        int right = htmlLowerCase.IndexOf(')');

        if (left < 0 || right < 0)
        {
            return Color.Empty;
        }

        string noBrackets = htmlLowerCase.Substring(left + 1, right - left - 1);

        string[] parts = noBrackets.Split(',');

        int r = int.Parse(parts[0], CultureInfo.InvariantCulture);
        int g = int.Parse(parts[1], CultureInfo.InvariantCulture);
        int b = int.Parse(parts[2], CultureInfo.InvariantCulture);

        if (parts.Length == 3)
        {
            return Color.FromArgb(r, g, b);
        }
        else if (parts.Length == 4)
        {
            float a = float.Parse(parts[3], CultureInfo.InvariantCulture);

            return Color.FromArgb((int)(a * 255), r, g, b);
        }

        return Color.Empty;
    }
}

测试:

    [TestMethod]
    public void ColorUtils_HtmlToColor()
    {
        Assert.AreEqual(Color.FromArgb(0x11, 0x22, 0x33), ColorUtils.HtmlToColor("#123"), "#123 (without alpha channel)");
        Assert.AreEqual(Color.FromArgb(0x11, 0x22, 0x33), ColorUtils.HtmlToColor("#112233"), "#112233 (without alpha channel)");
        Assert.AreEqual(Color.FromArgb(0x44, 0x11, 0x22, 0x33), ColorUtils.HtmlToColor("#1234"), "#1234 (alpha channel)");
        Assert.AreEqual(Color.FromArgb(0x44, 0x11, 0x22, 0x33), ColorUtils.HtmlToColor("#11223344"), "#11223344 (alpha channel)");
        Assert.AreEqual(Color.FromArgb(127, 11, 22, 33), ColorUtils.HtmlToColor("rgba(11,22,33,0.5)"), "rgba(11,22,33,0.5) (alpha channel)");
        Assert.AreEqual(Color.FromArgb(11, 22, 33), ColorUtils.HtmlToColor("rgb(11,22,33)"), "rgb(11,22,33) (alpha channel)");
        Assert.AreEqual(Color.Red, ColorUtils.HtmlToColor("red"), "red (named color)");
        Assert.AreEqual(Color.White, ColorUtils.HtmlToColor("white"), "white (named color)");
        Assert.AreEqual(Color.Blue, ColorUtils.HtmlToColor("blue"), "blue (named color)");
        Assert.AreEqual(Color.Empty, ColorUtils.HtmlToColor("invalid"), "invalid");
        Assert.AreEqual(Color.Empty, ColorUtils.HtmlToColor("#invalid"), "#invalid");
        Assert.AreEqual(Color.Empty, ColorUtils.HtmlToColor("rgb(invalid)"), "rgb(invalid)");
        Assert.AreEqual(Color.Empty, ColorUtils.HtmlToColor("rgba(invalid)"), "rgba(invalid)");
        Assert.AreEqual(Color.Empty, ColorUtils.HtmlToColor("rgba(invalid,invalid)"), "rgba(invalid,invalid)");
        Assert.AreEqual(Color.Empty, ColorUtils.HtmlToColor("rgb(11,22,333)"), "rgb(11,22,333) (value out of range)");
        Assert.AreEqual(Color.Empty, ColorUtils.HtmlToColor("rgba(11,22,333,0.5)"), "rgb(11,22,333,0.5) (value out of range)");
    }

【讨论】:

    【解决方案4】:

    有一个可用的用于颜色的 Selenium 库:

    import org.openqa.selenium.support.Color;
    
    String rgba = "rgba(1,1,1,1)";
    Color color = Color.fromString(rgba);
    System.out.println("hex value = " + color.asHex());
    

    【讨论】:

      【解决方案5】:

      这应该可以解决问题。

      public static string ConvertRgbaToHex(string rgba)
      {
          if (!Regex.IsMatch(rgba, @"rgba\((\d{1,3},\s*){3}(0(\.\d+)?|1)\)"))
                  throw new FormatException("rgba string was in a wrong format");
      
          var matches = Regex.Matches(rgba, @"\d+");
          StringBuilder hexaString = new StringBuilder("#");
      
          for(int i = 0; i < matches.Count - 1; i++)
          {
              int value = Int32.Parse(matches[i].Value);
      
              hexaString.Append(value.ToString("X"));
          }
      
          return hexaString.ToString();
      }
      

      测试用例:

      public class Program
      {
          static void Main(string[] args)
          {
              // Output: #192856
              Console.WriteLine(ConvertRgbaToHex("rgba(25, 40, 86, 1)"));
      
              Console.Read();
          }
      
          public static string ConvertRgbaToHex(string rgba)
          {
              if (!Regex.IsMatch(rgba, @"rgba\((\d{1,3},\s*){3}(0(\.\d+)?|1)\)"))
                      throw new FormatException("rgba string was in a wrong format");
      
              var matches = Regex.Matches(rgba, @"\d+");
              StringBuilder hexaString = new StringBuilder("#");
      
              for(int i = 0; i < matches.Count - 1; i++)
              {
                  int value = Int32.Parse(matches[i].Value);
      
                  hexaString.Append(value.ToString("X"));
              }
      
              return hexaString.ToString();
          }
      }
      

      【讨论】:

      • 这完全忽略了 alpha 通道。
      【解决方案6】:

      下面的代码从元素中选取style属性,并将rgb值转换为十六进制格式,然后比较值。

      string color = GetElement(LocateBy.XPath, "XpathOfTheElement").GetAttribute("style").ToString();
      string[] colorvalue1 = color.Split('(');
      
      string[] colorvalue2 = colorvalue1[1].Split(')');
      
      string colorvalue = colorvalue2[0].ToString();
      string[] ColorCodeRGBValue = colorvalue.Split(',');
      Color myColor = Color.FromArgb(Convert.ToInt32(ColorCodeRGBValue[0]), Convert.ToInt32(ColorCodeRGBValue[1]), Convert.ToInt32(ColorCodeRGBValue[2]));
      
      string hexValue = myColor.R.ToString("X2") + myColor.G.ToString("X2") + myColor.B.ToString("X2");
      
      Assert.AreEqual(hexValue , CsvReader.ColorCode,"Color codes are not equal");
      

      【讨论】:

        【解决方案7】:

        双向转换。我开发并测试了。

        public static string RgbaToHex(string value)
        {
            if (string.IsNullOrEmpty(value))
                return null;
            Color color;
            value = value.Trim();
            if (value.StartsWith("#"))
                color = ColorTranslator.FromHtml(value);
            else
            {
                if (!value.StartsWith("rgba"))
                    throw new FormatException("Not rgba string");
                var left = value.IndexOf('(');
                var right = value.IndexOf(')');
                if (left < 0 || right < 0)
                    throw new FormatException("rgba format error");
                var noBrackets = value.Substring(left + 1, right - left - 1);
                var parts = noBrackets.Split(',');
                var r = int.Parse(parts[0], CultureInfo.InvariantCulture);
                var g = int.Parse(parts[1], CultureInfo.InvariantCulture);
                var b = int.Parse(parts[2], CultureInfo.InvariantCulture);
                switch (parts.Length)
                {
                    case 3:
                        color = Color.FromArgb(r, g, b);
                        break;
                    case 4:
                    {
                        var a = float.Parse(parts[3], CultureInfo.InvariantCulture);
                        color = Color.FromArgb((int)(a * 255), r, g, b);
                        break;
                    }
                    default:
                        throw new FormatException("Not rgba string");
                }
            }
        
            return "#" + color.A.ToString("X2") + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
        }
        
        public static string HexToRgba(string value)
        {
            if (string.IsNullOrEmpty(value))
                return null;
            var argb = int.Parse(value.Replace("#", ""), NumberStyles.HexNumber);
            var clr = Color.FromArgb(argb);
            int r = Convert.ToInt16(clr.R);
            int g = Convert.ToInt16(clr.G);
            int b = Convert.ToInt16(clr.B);
            int a = Convert.ToInt16(clr.A);
            var trans = Math.Round((double)a / 255, 2).ToString("N2").Replace(",", ".");
            return $"rgba({r}, {g}, {b}, {trans})";
        }
        

        【讨论】:

          猜你喜欢
          • 2012-06-20
          • 2017-09-28
          • 2015-05-19
          • 2022-07-08
          • 2018-04-08
          • 2018-07-10
          • 2012-05-14
          • 2010-10-15
          相关资源
          最近更新 更多