简体   繁体   中英

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

I have Colors in a BGRA-Format which I get from a Delphi Application. I read these as a 8-Bit string into my C# Application. Now I try to convert these into the C# Color Format. The string I get looks like this:

string color = "$00FF00FF";

I tried to reconvert the Color and then Converting it to Int to Convert it to the System.Drawing Color

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

Where SplitByLenght is a function I found on SO (which I call from another 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));
    }
}

But somehow it doesn't work and I get the error:

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

I feel like the string isn't Converted to Int as supposed, but I didn't find any fixes. Can you either help me with the problem or have an alternative better approach to solve the problem?

To avoid string manipulations, you can remove the first char with string.Substring(1) , then use the Convert.ToInt32() overload which accepts a specific base ( 16 ) for the string conversion to a LE int .

BitConverter.GetBytes() can then be used to extract the bytes from the converted int and reverse the order.
► You may want to add a check before you reverse the byte order: if BitConverter.IsLittleEndian returns false, we're already using a BigEndian processor, so we don't reverse the order in this case.

Recompose the int value after and use either Color.FromArgb to return a Color that includes an Alpha channel or ColorTranslator.FromWin32 to ignore it (setting the Alpha channel to 255 no matter what: eg, if you need to use this color in a Control that doesn't support Color transparency).

I'm adding this method as a Sting extension ( string.ToARGBColor(bool) ). Name it as you prefer.

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

So you can just call it as:

string colorString = "$00FF00AA";
Color colorWithAlpha = colorString.ToARGBColor(true);
Color colorNoAlpha = colorString.ToARGBColor(false);

Using another classic BigEndian to LittleEndian conversion method:
(it should be slightly faster, maybe give it a test drive)

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

I apparently found a solution, simply had to use ColorTranslator.FromHtml(argb) instead of Color.FromArgb(Convert.ToInt32(argb, 16))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM