diff --git a/src/ImageProcessorCore/Colors/Color.cs b/src/ImageProcessorCore/Colors/Color.cs
index 80ee03e99..e82a1e3a8 100644
--- a/src/ImageProcessorCore/Colors/Color.cs
+++ b/src/ImageProcessorCore/Colors/Color.cs
@@ -6,6 +6,7 @@
namespace ImageProcessorCore
{
using System;
+ using System.Globalization;
using System.Numerics;
using System.Runtime.CompilerServices;
@@ -46,12 +47,11 @@ namespace ImageProcessorCore
{
get
{
- return (byte)this.packedValue;
+ return (byte)(this.packedValue >> 24);
}
set
{
- // AABBGGRR
- this.packedValue = (uint)(this.packedValue & -0x100 | value);
+ this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << 24;
}
}
@@ -63,12 +63,11 @@ namespace ImageProcessorCore
{
get
{
- return (byte)(this.packedValue >> 8);
+ return (byte)(this.packedValue >> 16);
}
set
{
- // AABBGGRR
- this.packedValue = (uint)(this.packedValue & -0xFF01 | (uint)value << 8);
+ this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << 16;
}
}
@@ -79,12 +78,11 @@ namespace ImageProcessorCore
{
get
{
- return (byte)(this.packedValue >> 16);
+ return (byte)(this.packedValue >> 8);
}
set
{
- // AABBGGRR
- this.packedValue = (uint)(this.packedValue & -0xFF0001 | (uint)(value << 16));
+ this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << 8;
}
}
@@ -95,12 +93,11 @@ namespace ImageProcessorCore
{
get
{
- return (byte)(this.packedValue >> 24);
+ return (byte)this.packedValue;
}
set
{
- // AABBGGRR
- this.packedValue = this.packedValue & 0xFFFFFF | (uint)value << 24;
+ this.packedValue = this.packedValue & 0xFFFFFF00 | value;
}
}
@@ -110,16 +107,15 @@ namespace ImageProcessorCore
public uint PackedValue { get { return this.packedValue; } set { this.packedValue = value; } }
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
/// The red component.
/// The green component.
/// The blue component.
/// The alpha component.
public Color(byte r, byte g, byte b, byte a = 255)
- : this()
{
- this.packedValue = (uint)(r | g << 8 | b << 16 | a << 24);
+ this.packedValue = (uint)(r << 24 | g << 16 | b << 8 | a);
}
///
@@ -127,46 +123,17 @@ namespace ImageProcessorCore
///
///
/// The hexadecimal representation of the combined color components arranged
- /// in rgb, rrggbb, or aarrggbb format to match web syntax.
+ /// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax.
///
public Color(string hex)
- : this()
{
- // Hexadecimal representations are layed out AARRGGBB to we need to do some reordering.
- hex = hex.StartsWith("#") ? hex.Substring(1) : hex;
+ Guard.NotNullOrEmpty(hex, nameof(hex));
- if (hex.Length != 8 && hex.Length != 6 && hex.Length != 3)
- {
- throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex));
- }
+ hex = ToRgbaHex(hex);
- if (hex.Length == 8)
- {
- this.packedValue =
- (uint)(Convert.ToByte(hex.Substring(2, 2), 16)
- | Convert.ToByte(hex.Substring(4, 2), 16) << 8
- | Convert.ToByte(hex.Substring(6, 2), 16) << 16
- | Convert.ToByte(hex.Substring(0, 2), 16) << 24);
- }
- else if (hex.Length == 6)
+ if (hex == null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out this.packedValue))
{
- this.packedValue =
- (uint)(Convert.ToByte(hex.Substring(0, 2), 16)
- | Convert.ToByte(hex.Substring(2, 2), 16) << 8
- | Convert.ToByte(hex.Substring(4, 2), 16) << 16
- | 255 << 24);
- }
- else
- {
- string rh = char.ToString(hex[0]);
- string gh = char.ToString(hex[1]);
- string bh = char.ToString(hex[2]);
-
- this.packedValue =
- (uint)(Convert.ToByte(rh + rh, 16)
- | Convert.ToByte(gh + gh, 16) << 8
- | Convert.ToByte(bh + bh, 16) << 16
- | 255 << 24);
+ throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex));
}
}
@@ -178,7 +145,6 @@ namespace ImageProcessorCore
/// The blue component.
/// The alpha component.
public Color(float r, float g, float b, float a = 1)
- : this()
{
this.packedValue = Pack(r, g, b, a);
}
@@ -190,7 +156,6 @@ namespace ImageProcessorCore
/// The vector containing the components for the packed vector.
///
public Color(Vector3 vector)
- : this()
{
this.packedValue = Pack(ref vector);
}
@@ -202,7 +167,6 @@ namespace ImageProcessorCore
/// The vector containing the components for the packed vector.
///
public Color(Vector4 vector)
- : this()
{
this.packedValue = Pack(ref vector);
}
@@ -217,7 +181,7 @@ namespace ImageProcessorCore
/// The on the right side of the operand.
///
///
- /// True if the current left is equal to the parameter; otherwise, false.
+ /// True if the parameter is equal to the parameter; otherwise, false.
///
public static bool operator ==(Color left, Color right)
{
@@ -230,7 +194,7 @@ namespace ImageProcessorCore
/// The on the left side of the operand.
/// The on the right side of the operand.
///
- /// True if the current left is equal to the parameter; otherwise, false.
+ /// True if the parameter is equal to the parameter; otherwise, false.
///
public static bool operator !=(Color left, Color right)
{
@@ -273,7 +237,7 @@ namespace ImageProcessorCore
///
public override int GetHashCode()
{
- return this.GetHashCode(this);
+ return this.packedValue.GetHashCode();
}
///
@@ -307,25 +271,42 @@ namespace ImageProcessorCore
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y, float z, float w)
{
- return (uint)((byte)Math.Round(x.Clamp(Zero, One) * MaxBytes)
- | ((byte)Math.Round(y.Clamp(Zero, One) * MaxBytes) << 8)
- | (byte)Math.Round(z.Clamp(Zero, One) * MaxBytes) << 16
- | (byte)Math.Round(w.Clamp(Zero, One) * MaxBytes) << 24);
+ return (uint)((byte)Math.Round(x.Clamp(Zero, One) * MaxBytes) << 24
+ | (byte)Math.Round(y.Clamp(Zero, One) * MaxBytes) << 16
+ | (byte)Math.Round(z.Clamp(Zero, One) * MaxBytes) << 8
+ | (byte)Math.Round(w.Clamp(Zero, One) * MaxBytes));
}
///
- /// Returns the hash code for this instance.
+ /// Converts the specified hex value to an rrggbbaa hex value.
///
- ///
- /// The instance of to return the hash code for.
- ///
+ /// The hex value to convert.
///
- /// A 32-bit signed integer that is the hash code for this instance.
+ /// A rrggbbaa hex value.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private int GetHashCode(Color packed)
+ private static string ToRgbaHex(string hex)
{
- return packed.packedValue.GetHashCode();
+ hex = hex.StartsWith("#") ? hex.Substring(1) : hex;
+
+ if (hex.Length == 8)
+ {
+ return hex;
+ }
+ else if (hex.Length == 6)
+ {
+ return hex + "FF";
+ }
+ else if (hex.Length < 3 || hex.Length > 4)
+ {
+ return null;
+ }
+
+ string red = char.ToString(hex[0]);
+ string green = char.ToString(hex[1]);
+ string blue = char.ToString(hex[2]);
+ string alpha = hex.Length == 3 ? "F" : char.ToString(hex[3]);
+
+ return red + red + green + green + blue + blue + alpha + alpha;
}
}
}
\ No newline at end of file
diff --git a/tests/ImageProcessorCore.Tests/Colors/ColorTests.cs b/tests/ImageProcessorCore.Tests/Colors/ColorTests.cs
index 82e1bd80e..a2f53694e 100644
--- a/tests/ImageProcessorCore.Tests/Colors/ColorTests.cs
+++ b/tests/ImageProcessorCore.Tests/Colors/ColorTests.cs
@@ -24,13 +24,15 @@ namespace ImageProcessorCore.Tests
Color color1 = new Color(0, 0, 0);
Color color2 = new Color(0, 0, 0, 1F);
Color color3 = new Color("#000");
- Color color4 = new Color("#000000");
- Color color5 = new Color("#FF000000");
+ Color color4 = new Color("#000F");
+ Color color5 = new Color("#000000");
+ Color color6 = new Color("#000000FF");
Assert.Equal(color1, color2);
Assert.Equal(color1, color3);
Assert.Equal(color1, color4);
Assert.Equal(color1, color5);
+ Assert.Equal(color1, color6);
}
///
@@ -94,9 +96,9 @@ namespace ImageProcessorCore.Tests
[Fact]
public void ConvertHex()
{
- const string First = "FF000000";
+ const string First = "000000FF";
Color color = Color.Black;
- string second = color.PackedValue.ToString("X");
+ string second = color.PackedValue.ToString("X8");
Assert.Equal(First, second);
}
}