C
C#5mo ago
Angius

✅ Hex color converter breaks on 3-digit and 4-digit values

I made this nifty lil' converter from hexadecimal strings to System.Drawing.Colors. It works perfectly for 6-digit and 8-digit values, but tests fail for 3-digit and 4-digit ones.
public static Color ParseHexColor(this string input)
{
var hex = input.Trim('#');
if (!int.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var num))
{
throw new ArgumentException("Not a valid hexadecimal number", nameof(input));
}

return hex.Length switch
{
3 => Color.FromArgb(((num >> 8) & 0xF) * 0xFF / 0xF, ((num >> 4) & 0xF) * 0xFF / 0xF, (num & 0xF) * 0xFF / 0xF),
4 => Color.FromArgb(((num >> 12) & 0xF) * 0xFF / 0xF,((num >> 8) & 0xF) * 0xFF / 0xF, ((num >> 4) & 0xF) * 0xFF / 0xF, (num & 0xF) * 0xFF / 0xF),
6 => Color.FromArgb((num >> 16) & 0xFF, (num >> 8) & 0xFF, num & 0xFF),
8 => Color.FromArgb((num >> 24) & 0xFF, (num >> 16) & 0xFF, (num >> 8) & 0xFF, num & 0xFF),
_ => throw new ArgumentException("Unknown format", nameof(input))
};
}
public static Color ParseHexColor(this string input)
{
var hex = input.Trim('#');
if (!int.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var num))
{
throw new ArgumentException("Not a valid hexadecimal number", nameof(input));
}

return hex.Length switch
{
3 => Color.FromArgb(((num >> 8) & 0xF) * 0xFF / 0xF, ((num >> 4) & 0xF) * 0xFF / 0xF, (num & 0xF) * 0xFF / 0xF),
4 => Color.FromArgb(((num >> 12) & 0xF) * 0xFF / 0xF,((num >> 8) & 0xF) * 0xFF / 0xF, ((num >> 4) & 0xF) * 0xFF / 0xF, (num & 0xF) * 0xFF / 0xF),
6 => Color.FromArgb((num >> 16) & 0xFF, (num >> 8) & 0xFF, num & 0xFF),
8 => Color.FromArgb((num >> 24) & 0xFF, (num >> 16) & 0xFF, (num >> 8) & 0xFF, num & 0xFF),
_ => throw new ArgumentException("Unknown format", nameof(input))
};
}
No description
No description
No description
No description
1 Reply
Angius
Angius5mo ago
Ah, derp, nevermind The test was faulty I was trying to assert that 4F0 produces Color.FromArgb(0x4, 0xF, 0x0) where it should've been Color.FromArgb(0x44, 0xFF, 0x00) since each digit in a 3-digit code needs to be duplicated Same for 4-digit codes