Browse Source

Merge pull request #20 from mellinoe/master

Ensure Color structure stores elements in RGBA order
pull/23/head
James Jackson-South 10 years ago
committed by GitHub
parent
commit
fd4ba861c6
  1. 37
      src/ImageSharp/Colors/Color.cs
  2. 18
      src/ImageSharp/PixelAccessor.cs
  3. 14
      tests/ImageSharp.Tests/Colors/ColorTests.cs
  4. 3
      tests/ImageSharp.Tests/project.json

37
src/ImageSharp/Colors/Color.cs

@ -19,6 +19,11 @@ namespace ImageSharp
/// </remarks> /// </remarks>
public partial struct Color : IPackedPixel<uint>, IEquatable<Color> public partial struct Color : IPackedPixel<uint>, IEquatable<Color>
{ {
private const int RedShift = 0;
private const int GreenShift = 8;
private const int BlueShift = 16;
private const int AlphaShift = 24;
/// <summary> /// <summary>
/// The maximum byte value. /// The maximum byte value.
/// </summary> /// </summary>
@ -63,6 +68,9 @@ namespace ImageSharp
{ {
throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); 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);
} }
/// <summary> /// <summary>
@ -106,12 +114,12 @@ namespace ImageSharp
{ {
get get
{ {
return (byte)(this.packedValue >> 24); return (byte)(this.packedValue >> RedShift);
} }
set set
{ {
this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << 24; this.packedValue = this.packedValue & 0xFFFFFF00 | (uint)value << RedShift;
} }
} }
@ -122,12 +130,12 @@ namespace ImageSharp
{ {
get get
{ {
return (byte)(this.packedValue >> 16); return (byte)(this.packedValue >> GreenShift);
} }
set set
{ {
this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << 16; this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << GreenShift;
} }
} }
@ -138,12 +146,12 @@ namespace ImageSharp
{ {
get get
{ {
return (byte)(this.packedValue >> 8); return (byte)(this.packedValue >> BlueShift);
} }
set set
{ {
this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << 8; this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << BlueShift;
} }
} }
@ -154,12 +162,12 @@ namespace ImageSharp
{ {
get get
{ {
return (byte)this.packedValue; return (byte)(this.packedValue >> AlphaShift);
} }
set set
{ {
this.packedValue = this.packedValue & 0xFFFFFF00 | value; this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << AlphaShift;
} }
} }
@ -234,7 +242,8 @@ namespace ImageSharp
/// <returns>A hexadecimal string representation of the value.</returns> /// <returns>A hexadecimal string representation of the value.</returns>
public string ToHex() public string ToHex()
{ {
return this.PackedValue.ToString("X8"); uint hexOrder = Pack(A, B, G, R);
return hexOrder.ToString("X8");
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -318,10 +327,10 @@ namespace ImageSharp
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One); vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
vector *= MaxBytes; vector *= MaxBytes;
vector += Half; vector += Half;
return (uint)(((byte)vector.X << 24) return (uint)(((byte)vector.X << RedShift)
| ((byte)vector.Y << 16) | ((byte)vector.Y << GreenShift)
| ((byte)vector.Z << 8) | ((byte)vector.Z << BlueShift)
| (byte)vector.W); | (byte)vector.W << AlphaShift);
} }
/// <summary> /// <summary>
@ -359,7 +368,7 @@ namespace ImageSharp
/// <returns>The <see cref="uint"/></returns> /// <returns>The <see cref="uint"/></returns>
private static uint Pack(byte x, byte y, byte z, byte w) 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);
} }
/// <summary> /// <summary>

18
src/ImageSharp/PixelAccessor.cs

@ -30,7 +30,7 @@ namespace ImageSharp
for (int x = 0; x < width; x++) 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; source += 3;
destination += 4; destination += 4;
@ -45,7 +45,7 @@ namespace ImageSharp
for (int x = 0; x < width; x++) 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; source += 4;
destination += 4; destination += 4;
@ -60,9 +60,9 @@ namespace ImageSharp
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
{ {
*destination = *(source + 1); *destination = *(source + 2);
*(destination + 1) = *(source + 2); *(destination + 1) = *(source + 1);
*(destination + 2) = *(source + 3); *(destination + 2) = *(source + 0);
source += 4; source += 4;
destination += 3; destination += 3;
@ -77,10 +77,10 @@ namespace ImageSharp
for (int x = 0; x < width; x++) for (int x = 0; x < width; x++)
{ {
*destination = *(source + 1); *destination = *(source + 2);
*(destination + 1) = *(source + 2); *(destination + 1) = *(source + 1);
*(destination + 2) = *(source + 3); *(destination + 2) = *(source + 0);
*(destination + 3) = *source; *(destination + 3) = *(source + 3);
source += 4; source += 4;
destination += 4; destination += 4;

14
tests/ImageSharp.Tests/Colors/ColorTests.cs

@ -117,5 +117,19 @@ namespace ImageSharp.Tests
Assert.Equal("00CCBBFF", color.ToHex()); Assert.Equal("00CCBBFF", color.ToHex());
} }
/// <summary>
/// Tests that the individual byte elements are layed out in RGBA order.
/// </summary>
[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]);
}
} }
} }

3
tests/ImageSharp.Tests/project.json

@ -10,7 +10,8 @@
] ]
}, },
"buildOptions": { "buildOptions": {
"debugType": "portable" "debugType": "portable",
"allowUnsafe": true
}, },
"dependencies": { "dependencies": {
"ImageSharp": "1.0.0-*", "ImageSharp": "1.0.0-*",

Loading…
Cancel
Save