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: e.g., 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);