将 BGRA 8 位十六进制字符串转换为 System.Drawing.Color

Converting BGRA 8-Bit Hexadecimal string into System.Drawing.Color

我有从 Delphi 应用程序获得的 BGRA 格式的颜色。我将这些作为 8 位字符串读取到我的 C# 应用程序中。现在我尝试将它们转换为 C# 颜色格式。我得到的字符串如下所示:

string color = "[=11=]FF00FF";

我尝试重新转换颜色,然后将其转换为 Int 以将其转换为 System.Drawing 颜色

private Color ConvertColorFromBgra(string color)
{
    string argb = "#";
    var bgra = FunctionLibrary.SplitByLength(color.Replace("$", ""), 2);
    foreach (var value in bgra.Revert())
    {
        argb += value;
    }
    return Color.FromArgb(Convert.ToInt32(argb, 16));
}

其中 SplitByLenght 是我在 SO 上找到的函数(我从另一个 Class 调用):

public static IEnumerable<string> SplitByLength(this string str, int maxLength)
{
    for (int index = 0; index < str.Length; index += maxLength)
    {
        yield return str.Substring(index, Math.Min(maxLength, str.Length - index));
    }
}

但不知何故它不起作用,我收到错误消息:

System.FormatException: 'Could not find any recognizable digits.

我觉得字符串没有按预期转换为 Int,但我没有找到任何修复方法。你能帮我解决这个问题,或者有其他更好的方法来解决这个问题吗?

我显然找到了解决方案,只需要使用 ColorTranslator.FromHtml(argb) 而不是 Color.FromArgb(Convert.ToInt32(argb, 16))

为避免字符串操作,您可以使用 string.Substring(1) 删除第一个字符,然后使用接受特定基数 (16) 的 Convert.ToInt32() 重载将字符串转换为LE int.

BitConverter.GetBytes() 然后可用于从转换后的 int 中提取字节并反转顺序。
► 您可能希望在反转字节顺序之前添加一个检查:如果 BitConverter.IsLittleEndian returns 为假,我们已经在使用 BigEndian 处理器,因此在这种情况下我们不会反转顺序。

之后重新组合 int 值并使用 Color.FromArgb to return a Color that includes an Alpha channel or ColorTranslator.FromWin32 忽略它(将 Alpha 通道设置为 255 无论如何:例如,如果您需要在不支持颜色透明度的控件)。

我将此方法添加为 Sting 扩展 (string.ToARGBColor(bool))。随意命名。

public static class StringsExtensions
{
    public static Color ToARGBColor(this string hexColor, bool includeAlpha)
    {
        int ci = BitConverter.ToInt32(BitConverter.GetBytes(
            Convert.ToInt32(hexColor.Substring(1), 16)).Reverse().ToArray(), 0);
        return includeAlpha ? Color.FromArgb(ci) : ColorTranslator.FromWin32(ci);
    }
}

因此您可以将其命名为:

string colorString = "[=11=]FF00AA";
Color colorWithAlpha = colorString.ToARGBColor(true);
Color colorNoAlpha = colorString.ToARGBColor(false);

使用另一种经典的BigEndian到LittleEndian的转换方法:
(应该会稍微快一点,可以试驾一下)

byte[] b = BitConverter.GetBytes(Convert.ToInt32(colorString.Substring(1), 16));
int ci = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
Color c = Color.FromArgb(ci);