So I’m working on a side project to load in XML maps generated by Matt Thorson’s Ogmo Editor. It turns out that he uses hex values to define his ARGB colors. You know, #FFFFFFFF for white, #FF000000 for black, etc.
XNA’s default Color implementation doesn’t have anyway to read to or from hex values, and a quick search on Google didn’t turn up anything very relevant on a cursory glance. So I just whipped up a helper class couple of extension classes to read and convert ARGB or RGB hex strings (with or without the hash mark) to Microsoft.Xna.Framework.Graphics.Color values, and vice versa.
Feel free to use this wherever you see fit. Code below the jump.
05/14/10 Edit: Via the suggestions offered by Chris in the comments below, I’ve re-worked the code to be a bit less heavy on the string manipulation. I’ve also gone ahead and split the static color helper class into two separate extension classes that each work on their respective types. I think that makes the usability a bit nicer. Thanks, Chris!
C#
public static class ColorExtensions
{
/// <summary>
/// Creates an ARGB hex string representation of the <see cref="Color"/> value.
/// </summary>
/// <param name="color">The <see cref="Color"/> value to parse.</param>
/// <param name="includeHash">Determines whether to include the hash mark (#) character in the string.</param>
/// <returns>Returns a hex string representation of the specified <see cref="Color"/> value.</returns>
public static string ToHex(this Color color, bool includeHash)
{
string[] argb = {
color.A.ToString("X2"),
color.R.ToString("X2"),
color.G.ToString("X2"),
color.B.ToString("X2"),
};
return (includeHash ? "#" : string.Empty) + string.Join(string.Empty, argb);
}
}
public static class StringExtensions
{
/// <summary>
/// Creates a <see cref="Color"/> value from an ARGB or RGB hex string. The string may begin with or without the
/// hash mark (#) character.
/// </summary>
/// <param name="hexString">The ARGB hex string to parse.</param>
/// <returns>Returns a <see cref="Color"/> value as defined by the ARGB or RGB hex string.</returns>
/// <exception cref="InvalidOperationException">Thrown if the string is not a valid ARGB or RGB hex value.</exception>
public static Color ToColor(this string hexString)
{
if (hexString.StartsWith("#"))
hexString = hexString.Substring(1);
uint hex = uint.Parse(hexString, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture);
Color color = Color.White;
if (hexString.Length == 8)
{
color.A = (byte)(hex >> 24);
color.R = (byte)(hex >> 16);
color.G = (byte)(hex >> 8);
color.B = (byte)(hex);
}
else if (hexString.Length == 6)
{
color.R = (byte)(hex >> 16);
color.G = (byte)(hex >> 8);
color.B = (byte)(hex);
}
else
{
throw new InvalidOperationException("Invald hex representation of an ARGB or RGB color value.");
}
return color;
}
}
3 Comments
You can avoid so much string splitting and parsing by parsing the whole number in one go then using bitshifting to get the components, something like:
var c = uint.Parse(hexcode.Substring(1), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
var a = (c >> 6) & 0xFF;
var r = (c >> 4) & 0xFF;
var g = (c >> 2) & 0xFF;
var b = c & 0xFF;
Note, its un-tested, I just wrote it out quickly as a demonstration, but thats the general principle.
@Chris Awesome! I guess not immediately thinking of utilizing some bit operations to extract the components really goes to show my hobbyist approach to this! :)
Thanks for the suggestions. I’ve gone ahead and updated the code by using this approach, and by splitting it into two separate extension classes.
Awesome! Thanks for this, and updated the moment I search for it in google! I was going to write up my own extension if I didn’t find one, now I don’t have to :)
Thanks!
One Trackback
[...] a color from HEX is another thing that isn’t built into XNA. So, back to google and I found this blog that had the extensions I needed already worked out! Ok, fantastic, now the final piece, I just [...]