diff --git a/src/ImageSharp/Colors/Color.cs b/src/ImageSharp/Colors/Color.cs index 633a1c0144..edd0fd0f09 100644 --- a/src/ImageSharp/Colors/Color.cs +++ b/src/ImageSharp/Colors/Color.cs @@ -19,6 +19,11 @@ namespace ImageSharp /// public partial struct Color : IPackedPixel, IEquatable { + private const int RedShift = 0; + private const int GreenShift = 8; + private const int BlueShift = 16; + private const int AlphaShift = 24; + /// /// The maximum byte value. /// @@ -63,6 +68,9 @@ namespace ImageSharp { throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); } + + // Order parsed from hex string will be backwards, so reverse it. + packedValue = Pack(A, B, G, R); } /// @@ -106,12 +114,12 @@ namespace ImageSharp { get { - return (byte)(this.packedValue >> 24); + return (byte)(this.packedValue >> RedShift); } set { - this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << 24; + this.packedValue = this.packedValue & 0xFFFFFF00 | (uint)value << RedShift; } } @@ -122,12 +130,12 @@ namespace ImageSharp { get { - return (byte)(this.packedValue >> 16); + return (byte)(this.packedValue >> GreenShift); } set { - this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << 16; + this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << GreenShift; } } @@ -138,12 +146,12 @@ namespace ImageSharp { get { - return (byte)(this.packedValue >> 8); + return (byte)(this.packedValue >> BlueShift); } set { - this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << 8; + this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << BlueShift; } } @@ -154,12 +162,12 @@ namespace ImageSharp { get { - return (byte)this.packedValue; + return (byte)(this.packedValue >> AlphaShift); } set { - this.packedValue = this.packedValue & 0xFFFFFF00 | value; + this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << AlphaShift; } } @@ -234,7 +242,8 @@ namespace ImageSharp /// A hexadecimal string representation of the value. public string ToHex() { - return this.PackedValue.ToString("X8"); + uint hexOrder = Pack(A, B, G, R); + return hexOrder.ToString("X8"); } /// @@ -318,10 +327,10 @@ namespace ImageSharp vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One); vector *= MaxBytes; vector += Half; - return (uint)(((byte)vector.X << 24) - | ((byte)vector.Y << 16) - | ((byte)vector.Z << 8) - | (byte)vector.W); + return (uint)(((byte)vector.X << RedShift) + | ((byte)vector.Y << GreenShift) + | ((byte)vector.Z << BlueShift) + | (byte)vector.W << AlphaShift); } /// @@ -359,7 +368,7 @@ namespace ImageSharp /// The private static uint Pack(byte x, byte y, byte z, byte w) { - return (uint)(x << 24 | y << 16 | z << 8 | w); + return (uint)(x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift); } /// diff --git a/src/ImageSharp/PixelAccessor.cs b/src/ImageSharp/PixelAccessor.cs index d67aa7f2a9..5c2ec5065f 100644 --- a/src/ImageSharp/PixelAccessor.cs +++ b/src/ImageSharp/PixelAccessor.cs @@ -30,7 +30,7 @@ namespace ImageSharp for (int x = 0; x < width; x++) { - Unsafe.Write(destination, (uint)(*(source + 2) << 24 | *(source + 1) << 16 | *source << 8 | 255)); + Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | 255 << 24)); source += 3; destination += 4; @@ -45,7 +45,7 @@ namespace ImageSharp for (int x = 0; x < width; x++) { - Unsafe.Write(destination, (uint)(*(source + 2) << 24 | *(source + 1) << 16 | *source << 8 | *(source + 3))); + Unsafe.Write(destination, (uint)(*(source + 2) << 0 | *(source + 1) << 8 | *source << 16 | *(source + 3) << 24)); source += 4; destination += 4; @@ -60,9 +60,9 @@ namespace ImageSharp for (int x = 0; x < width; x++) { - *destination = *(source + 1); - *(destination + 1) = *(source + 2); - *(destination + 2) = *(source + 3); + *destination = *(source + 2); + *(destination + 1) = *(source + 1); + *(destination + 2) = *(source + 0); source += 4; destination += 3; @@ -77,10 +77,10 @@ namespace ImageSharp for (int x = 0; x < width; x++) { - *destination = *(source + 1); - *(destination + 1) = *(source + 2); - *(destination + 2) = *(source + 3); - *(destination + 3) = *source; + *destination = *(source + 2); + *(destination + 1) = *(source + 1); + *(destination + 2) = *(source + 0); + *(destination + 3) = *(source + 3); source += 4; destination += 4; diff --git a/tests/ImageSharp.Tests/Colors/ColorTests.cs b/tests/ImageSharp.Tests/Colors/ColorTests.cs index ac7ef81237..23ebbec986 100644 --- a/tests/ImageSharp.Tests/Colors/ColorTests.cs +++ b/tests/ImageSharp.Tests/Colors/ColorTests.cs @@ -117,5 +117,19 @@ namespace ImageSharp.Tests Assert.Equal("00CCBBFF", color.ToHex()); } + + /// + /// Tests that the individual byte elements are layed out in RGBA order. + /// + [Fact] + public unsafe void ByteLayout() + { + Color color = new Color(1, 2, 3, 4); + byte* colorBase = (byte*)&color; + Assert.Equal(1, colorBase[0]); + Assert.Equal(2, colorBase[1]); + Assert.Equal(3, colorBase[2]); + Assert.Equal(4, colorBase[3]); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/project.json b/tests/ImageSharp.Tests/project.json index f81cbfe824..b9b7b50ab6 100644 --- a/tests/ImageSharp.Tests/project.json +++ b/tests/ImageSharp.Tests/project.json @@ -10,7 +10,8 @@ ] }, "buildOptions": { - "debugType": "portable" + "debugType": "portable", + "allowUnsafe": true }, "dependencies": { "ImageSharp": "1.0.0-*",