diff --git a/src/ImageSharp/Colors/ColorVector.cs b/src/ImageSharp/Colors/ColorVector.cs
index 3e86e85c75..354553982a 100644
--- a/src/ImageSharp/Colors/ColorVector.cs
+++ b/src/ImageSharp/Colors/ColorVector.cs
@@ -218,9 +218,10 @@ namespace ImageSharp
/// A hexadecimal string representation of the value.
public string ToHex()
{
+ // Hex is RRGGBBAA
Vector4 vector = this.backingVector * MaxBytes;
vector += Half;
- uint hexOrder = (uint)((byte)vector.X | (byte)vector.Y << 8 | (byte)vector.Z << 16 | (byte)vector.W << 24);
+ uint hexOrder = (uint)((byte)vector.W | (byte)vector.Z << 8 | (byte)vector.Y << 16 | (byte)vector.X << 24);
return hexOrder.ToString("X8");
}
@@ -244,7 +245,7 @@ namespace ImageSharp
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
- bytes[startIndex + 2] = (byte)vector.W;
+ bytes[startIndex + 3] = (byte)vector.W;
}
///
@@ -267,7 +268,7 @@ namespace ImageSharp
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
- bytes[startIndex + 2] = (byte)vector.W;
+ bytes[startIndex + 3] = (byte)vector.W;
}
///
diff --git a/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs b/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs
index b5b09c8288..42481799f1 100644
--- a/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs
+++ b/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs
@@ -33,6 +33,7 @@ namespace ImageSharp.Tests.Colors
{ new NormalizedShort4(Vector4.One), new NormalizedShort4(Vector4.One), typeof(NormalizedShort4) },
{ new Rg32(Vector2.One), new Rg32(Vector2.One), typeof(Rg32) },
{ new Rgba1010102(Vector4.One), new Rgba1010102(Vector4.One), typeof(Rgba1010102) },
+ { new Rgba32(Vector4.One), new Rgba32(Vector4.One), typeof(Rgba32) },
{ new Rgba64(Vector4.One), new Rgba64(Vector4.One), typeof(Rgba64) },
{ new Short2(Vector2.One * 0x7FFF), new Short2(Vector2.One * 0x7FFF), typeof(Short2) },
{ new Short4(Vector4.One * 0x7FFF), new Short4(Vector4.One * 0x7FFF), typeof(Short4) },
@@ -144,6 +145,7 @@ namespace ImageSharp.Tests.Colors
{ new NormalizedShort4(Vector4.One), new NormalizedShort4(Vector4.Zero), typeof(NormalizedShort4) },
{ new Rg32(Vector2.One), new Rg32(Vector2.Zero), typeof(Rg32) },
{ new Rgba1010102(Vector4.One), new Rgba1010102(Vector4.Zero), typeof(Rgba1010102) },
+ { new Rgba32(Vector4.One), new Rgba32(Vector4.Zero), typeof(Rgba32) },
{ new Rgba64(Vector4.One), new Rgba64(Vector4.Zero), typeof(Rgba64) },
{ new Short2(Vector2.One * 0x7FFF), new Short2(Vector2.Zero), typeof(Short2) },
{ new Short4(Vector4.One * 0x7FFF), new Short4(Vector4.Zero), typeof(Short4) },
@@ -289,10 +291,10 @@ namespace ImageSharp.Tests.Colors
[MemberData(nameof(EqualityDataColorSpaces))]
public void EqualityObject(object first, object second, Type type)
{
- // Arrange
- // Cast to the known object types, this is so that we can hit the
- // equality operator on the concrete type, otherwise it goes to the
- // default "object" one :)
+ // Arrange
+ // Cast to the known object types, this is so that we can hit the
+ // equality operator on the concrete type, otherwise it goes to the
+ // default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
@@ -308,10 +310,10 @@ namespace ImageSharp.Tests.Colors
[MemberData(nameof(NotEqualityDataColorSpaces))]
public void NotEqualityObject(object first, object second, Type type)
{
- // Arrange
- // Cast to the known object types, this is so that we can hit the
- // equality operator on the concrete type, otherwise it goes to the
- // default "object" one :)
+ // Arrange
+ // Cast to the known object types, this is so that we can hit the
+ // equality operator on the concrete type, otherwise it goes to the
+ // default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
@@ -327,10 +329,10 @@ namespace ImageSharp.Tests.Colors
[MemberData(nameof(EqualityDataColorSpaces))]
public void EqualityOperator(object first, object second, Type type)
{
- // Arrange
- // Cast to the known object types, this is so that we can hit the
- // equality operator on the concrete type, otherwise it goes to the
- // default "object" one :)
+ // Arrange
+ // Cast to the known object types, this is so that we can hit the
+ // equality operator on the concrete type, otherwise it goes to the
+ // default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
@@ -346,10 +348,10 @@ namespace ImageSharp.Tests.Colors
[MemberData(nameof(NotEqualityDataColorSpaces))]
public void NotEqualityOperator(object first, object second, Type type)
{
- // Arrange
- // Cast to the known object types, this is so that we can hit the
- // equality operator on the concrete type, otherwise it goes to the
- // default "object" one :)
+ // Arrange
+ // Cast to the known object types, this is so that we can hit the
+ // equality operator on the concrete type, otherwise it goes to the
+ // default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
@@ -364,10 +366,10 @@ namespace ImageSharp.Tests.Colors
[MemberData(nameof(AlmostEqualsData))]
public void AlmostEquals(object first, object second, Type type, float precision)
{
- // Arrange
- // Cast to the known object types, this is so that we can hit the
- // equality operator on the concrete type, otherwise it goes to the
- // default "object" one :)
+ // Arrange
+ // Cast to the known object types, this is so that we can hit the
+ // equality operator on the concrete type, otherwise it goes to the
+ // default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
@@ -382,10 +384,10 @@ namespace ImageSharp.Tests.Colors
[MemberData(nameof(AlmostNotEqualsData))]
public void AlmostNotEquals(object first, object second, Type type, float precision)
{
- // Arrange
- // Cast to the known object types, this is so that we can hit the
- // equality operator on the concrete type, otherwise it goes to the
- // default "object" one :)
+ // Arrange
+ // Cast to the known object types, this is so that we can hit the
+ // equality operator on the concrete type, otherwise it goes to the
+ // default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
diff --git a/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs b/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs
index 3e2b6fcd5c..b5e159d9ae 100644
--- a/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs
+++ b/tests/ImageSharp.Tests/Colors/PackedPixelTests.cs
@@ -711,6 +711,51 @@ namespace ImageSharp.Tests.Colors
Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 });
}
+ [Fact]
+ public void Rgba32()
+ {
+ // Test the limits.
+ Assert.Equal((uint)0x0, new Rgba32(Vector4.Zero).PackedValue);
+ Assert.Equal(0xFFFFFFFF, new Rgba32(Vector4.One).PackedValue);
+
+ // Test ToVector4.
+ Assert.True(Equal(Vector4.One, new Rgba32(Vector4.One).ToVector4()));
+ Assert.True(Equal(Vector4.Zero, new Rgba32(Vector4.Zero).ToVector4()));
+ Assert.True(Equal(Vector4.UnitX, new Rgba32(Vector4.UnitX).ToVector4()));
+ Assert.True(Equal(Vector4.UnitY, new Rgba32(Vector4.UnitY).ToVector4()));
+ Assert.True(Equal(Vector4.UnitZ, new Rgba32(Vector4.UnitZ).ToVector4()));
+ Assert.True(Equal(Vector4.UnitW, new Rgba32(Vector4.UnitW).ToVector4()));
+
+ // Test clamping.
+ Assert.True(Equal(Vector4.Zero, new Rgba32(Vector4.One * -1234.0f).ToVector4()));
+ Assert.True(Equal(Vector4.One, new Rgba32(Vector4.One * +1234.0f).ToVector4()));
+
+ float x = +0.1f;
+ float y = -0.3f;
+ float z = +0.5f;
+ float w = -0.7f;
+ Rgba32 rgba32 = new Rgba32(x, y, z, w);
+ Assert.Equal(0x80001Au, rgba32.PackedValue);
+
+ // Test ordering
+ byte[] rgb = new byte[3];
+ byte[] rgba = new byte[4];
+ byte[] bgr = new byte[3];
+ byte[] bgra = new byte[4];
+
+ rgba32.ToXyzBytes(rgb, 0);
+ Assert.Equal(rgb, new byte[] { 0x1a, 0, 0x80 });
+
+ rgba32.ToXyzwBytes(rgba, 0);
+ Assert.Equal(rgba, new byte[] { 0x1a, 0, 0x80, 0 });
+
+ rgba32.ToZyxBytes(bgr, 0);
+ Assert.Equal(bgr, new byte[] { 0x80, 0, 0x1a });
+
+ rgba32.ToZyxwBytes(bgra, 0);
+ Assert.Equal(bgra, new byte[] { 0x80, 0, 0x1a, 0 });
+ }
+
[Fact]
public void Rgba64()
{
diff --git a/tests/ImageSharp.Tests/Colors/UnPackedPixelTests.cs b/tests/ImageSharp.Tests/Colors/UnPackedPixelTests.cs
new file mode 100644
index 0000000000..4fb189ca81
--- /dev/null
+++ b/tests/ImageSharp.Tests/Colors/UnPackedPixelTests.cs
@@ -0,0 +1,148 @@
+namespace ImageSharp.Tests.Colors
+{
+ using System.Numerics;
+
+ using Xunit;
+
+ public class UnPackedPixelTests
+ {
+ [Fact]
+ public void Color_Types_From_Bytes_Produce_Equal_Scaled_Component_OutPut()
+ {
+ Color color = new Color(24, 48, 96, 192);
+ ColorVector colorVector = new ColorVector(24, 48, 96, 192);
+
+ Assert.Equal(color.R, (byte)(colorVector.R * 255));
+ Assert.Equal(color.G, (byte)(colorVector.G * 255));
+ Assert.Equal(color.B, (byte)(colorVector.B * 255));
+ Assert.Equal(color.A, (byte)(colorVector.A * 255));
+ }
+
+ [Fact]
+ public void Color_Types_From_Floats_Produce_Equal_Scaled_Component_OutPut()
+ {
+ Color color = new Color(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F);
+ ColorVector colorVector = new ColorVector(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F);
+
+ Assert.Equal(color.R, (byte)(colorVector.R * 255));
+ Assert.Equal(color.G, (byte)(colorVector.G * 255));
+ Assert.Equal(color.B, (byte)(colorVector.B * 255));
+ Assert.Equal(color.A, (byte)(colorVector.A * 255));
+ }
+
+ [Fact]
+ public void Color_Types_From_Vector4_Produce_Equal_Scaled_Component_OutPut()
+ {
+ Color color = new Color(new Vector4(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F));
+ ColorVector colorVector = new ColorVector(new Vector4(24 / 255F, 48 / 255F, 96 / 255F, 192 / 255F));
+
+ Assert.Equal(color.R, (byte)(colorVector.R * 255));
+ Assert.Equal(color.G, (byte)(colorVector.G * 255));
+ Assert.Equal(color.B, (byte)(colorVector.B * 255));
+ Assert.Equal(color.A, (byte)(colorVector.A * 255));
+ }
+
+ [Fact]
+ public void Color_Types_From_Vector3_Produce_Equal_Scaled_Component_OutPut()
+ {
+ Color color = new Color(new Vector3(24 / 255F, 48 / 255F, 96 / 255F));
+ ColorVector colorVector = new ColorVector(new Vector3(24 / 255F, 48 / 255F, 96 / 255F));
+
+ Assert.Equal(color.R, (byte)(colorVector.R * 255));
+ Assert.Equal(color.G, (byte)(colorVector.G * 255));
+ Assert.Equal(color.B, (byte)(colorVector.B * 255));
+ Assert.Equal(color.A, (byte)(colorVector.A * 255));
+ }
+
+ [Fact]
+ public void Color_Types_From_Hex_Produce_Equal_Scaled_Component_OutPut()
+ {
+ Color color = Color.FromHex("183060C0");
+ ColorVector colorVector = ColorVector.FromHex("183060C0");
+
+ Assert.Equal(color.R, (byte)(colorVector.R * 255));
+ Assert.Equal(color.G, (byte)(colorVector.G * 255));
+ Assert.Equal(color.B, (byte)(colorVector.B * 255));
+ Assert.Equal(color.A, (byte)(colorVector.A * 255));
+ }
+
+ [Fact]
+ public void Color_Types_To_Vector4_Produce_Equal_OutPut()
+ {
+ Color color = new Color(24, 48, 96, 192);
+ ColorVector colorVector = new ColorVector(24, 48, 96, 192);
+
+ Assert.Equal(color.ToVector4(), colorVector.ToVector4());
+ }
+
+ [Fact]
+ public void Color_Types_To_RgbBytes_Produce_Equal_OutPut()
+ {
+ Color color = new Color(24, 48, 96, 192);
+ ColorVector colorVector = new ColorVector(24, 48, 96, 192);
+
+ byte[] rgb = new byte[3];
+ byte[] rgbVector = new byte[3];
+
+ color.ToXyzBytes(rgb, 0);
+ colorVector.ToXyzBytes(rgbVector, 0);
+
+ Assert.Equal(rgb, rgbVector);
+ }
+
+ [Fact]
+ public void Color_Types_To_RgbaBytes_Produce_Equal_OutPut()
+ {
+ Color color = new Color(24, 48, 96, 192);
+ ColorVector colorVector = new ColorVector(24, 48, 96, 192);
+
+ byte[] rgba = new byte[4];
+ byte[] rgbaVector = new byte[4];
+
+ color.ToXyzwBytes(rgba, 0);
+ colorVector.ToXyzwBytes(rgbaVector, 0);
+
+ Assert.Equal(rgba, rgbaVector);
+ }
+
+ [Fact]
+ public void Color_Types_To_BgrBytes_Produce_Equal_OutPut()
+ {
+ Color color = new Color(24, 48, 96, 192);
+ ColorVector colorVector = new ColorVector(24, 48, 96, 192);
+
+ byte[] bgr = new byte[3];
+ byte[] bgrVector = new byte[3];
+
+ color.ToZyxBytes(bgr, 0);
+ colorVector.ToZyxBytes(bgrVector, 0);
+
+ Assert.Equal(bgr, bgrVector);
+ }
+
+ [Fact]
+ public void Color_Types_To_BgraBytes_Produce_Equal_OutPut()
+ {
+ Color color = new Color(24, 48, 96, 192);
+ ColorVector colorVector = new ColorVector(24, 48, 96, 192);
+
+ byte[] bgra = new byte[4];
+ byte[] bgraVector = new byte[4];
+
+ color.ToZyxwBytes(bgra, 0);
+ colorVector.ToZyxwBytes(bgraVector, 0);
+
+ Assert.Equal(bgra, bgraVector);
+ }
+
+ [Fact]
+ public void Color_Types_To_Hex_Produce_Equal_OutPut()
+ {
+ Color color = new Color(24, 48, 96, 192);
+ ColorVector colorVector = new ColorVector(24, 48, 96, 192);
+
+ // 183060C0
+ Assert.Equal(color.ToHex(), colorVector.ToHex());
+ }
+ }
+}
\ No newline at end of file