Skip to content

Commit

Permalink
Unify and improve FromHex in ColorHelper.cs and ColorExtensions.cs
Browse files Browse the repository at this point in the history
* Both now use ColorHelper.FromHex, rather than differing implementations

* FromHex now accepts hex numbers with three and four digits matching HTML color codes, where "ABC" maps to "AABBCC"

* Significant performance increase using bitshifts over string operations
  • Loading branch information
Eb3yr committed Nov 6, 2024
1 parent a0613cf commit 2127212
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 13 deletions.
6 changes: 1 addition & 5 deletions source/MonoGame.Extended/ColorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ public static class ColorExtensions
{
public static Color FromHex(string value)
{
var r = int.Parse(value.Substring(1, 2), NumberStyles.HexNumber);
var g = int.Parse(value.Substring(3, 2), NumberStyles.HexNumber);
var b = int.Parse(value.Substring(5, 2), NumberStyles.HexNumber);
var a = value.Length > 7 ? int.Parse(value.Substring(7, 2), NumberStyles.HexNumber) : 255;
return new Color(r, g, b, a);
return ColorHelper.FromHex(value);
}

public static Color ToRgb(this HslColor c)
Expand Down
48 changes: 40 additions & 8 deletions source/MonoGame.Extended/ColorHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,45 @@ public static Color FromHex(string value)
{
if (string.IsNullOrEmpty(value))
return Color.Transparent;
var startIndex = 0;
if (value.StartsWith("#"))
startIndex++;
var r = int.Parse(value.Substring(startIndex, 2), NumberStyles.HexNumber);
var g = int.Parse(value.Substring(startIndex + 2, 2), NumberStyles.HexNumber);
var b = int.Parse(value.Substring(startIndex + 4, 2), NumberStyles.HexNumber);
var a = value.Length > 6 + startIndex ? int.Parse(value.Substring(startIndex + 6, 2), NumberStyles.HexNumber) : 255;

if (value[0] == '#')
value = value.Substring(1);

int r, g, b, a;
uint hexInt = uint.Parse(value, System.Globalization.NumberStyles.HexNumber);
switch (value.Length)
{
case 6:
r = (byte)((hexInt & 0x00FF0000) >> 16);
g = (byte)((hexInt & 0x0000FF00) >> 8);
b = (byte)(hexInt & 0x000000FF);
a = 255;
break;

case 8:
r = (byte)((hexInt & 0xFF000000) >> 24);
g = (byte)((hexInt & 0x00FF0000) >> 16);
b = (byte)((hexInt & 0x0000FF00) >> 8);
a = (byte)(hexInt & 0x000000FF);
break;

case 3:
r = (byte)(((hexInt & 0x00000F00) | (hexInt & 0x00000F00) << 4) >> 8);
g = (byte)(((hexInt & 0x000000F0) | (hexInt & 0x000000F0) << 4) >> 4);
b = (byte)((hexInt & 0x0000000F) | (hexInt & 0x0000000F) << 4);
a = 255;
break;

case 4:
r = (byte)(((hexInt & 0x0000F000) | (hexInt & 0x0000F000) << 4) >> 12);
g = (byte)(((hexInt & 0x00000F00) | (hexInt & 0x00000F00) << 4) >> 8);
b = (byte)(((hexInt & 0x000000F0) | (hexInt & 0x000000F0) << 4) >> 4);
a = (byte)((hexInt & 0x0000000F) | (hexInt & 0x0000000F) << 4);
break;

default:
throw new ArgumentException($"Malformed hexadecimal color: {value}");
}

return new Color(r, g, b, a);
}
Expand Down Expand Up @@ -80,4 +112,4 @@ public static Color FromName(string name)
throw new InvalidOperationException($"{name} is not a valid color");
}
}
}
}

0 comments on commit 2127212

Please sign in to comment.