diff --git a/src/ImageSharp/Colors/Color.cs b/src/ImageSharp/Colors/Color.cs
index fb2ce38ac..fa83429df 100644
--- a/src/ImageSharp/Colors/Color.cs
+++ b/src/ImageSharp/Colors/Color.cs
@@ -10,7 +10,7 @@ namespace ImageSharp
using System.Runtime.InteropServices;
///
- /// Unpacked pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
+ /// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in red, green, blue, and alpha order.
///
///
@@ -18,7 +18,7 @@ namespace ImageSharp
/// as it avoids the need to create new values for modification operations.
///
[StructLayout(LayoutKind.Explicit)]
- public partial struct Color : IPixel
+ public partial struct Color : IPixel, IPackedVector
{
///
/// Gets or sets the red component.
@@ -44,6 +44,12 @@ namespace ImageSharp
[FieldOffset(3)]
public byte A;
+ ///
+ /// The packed representation of the value.
+ ///
+ [FieldOffset(0)]
+ public uint Rgba;
+
///
/// The shift count for the red component
///
@@ -81,6 +87,7 @@ namespace ImageSharp
/// The green component.
/// The blue component.
/// The alpha component.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Color(byte r, byte g, byte b, byte a = 255)
: this()
{
@@ -97,10 +104,11 @@ namespace ImageSharp
/// The green component.
/// The blue component.
/// The alpha component.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Color(float r, float g, float b, float a = 1)
: this()
{
- this = Pack(r, g, b, a);
+ this.Pack(r, g, b, a);
}
///
@@ -109,10 +117,11 @@ namespace ImageSharp
///
/// The vector containing the components for the packed vector.
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Color(Vector3 vector)
: this()
{
- this = Pack(ref vector);
+ this.Pack(ref vector);
}
///
@@ -121,12 +130,29 @@ namespace ImageSharp
///
/// The vector containing the components for the packed vector.
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Color(Vector4 vector)
: this()
{
- this = Pack(ref vector);
+ this = PackNew(ref vector);
+ }
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ ///
+ /// The packed value.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Color(uint packed)
+ : this()
+ {
+ this.Rgba = packed;
}
+ ///
+ public uint PackedValue { get => this.Rgba; set => this.Rgba = value; }
+
///
/// Compares two objects for equality.
///
@@ -142,10 +168,7 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Color left, Color right)
{
- return left.R == right.R
- && left.G == right.G
- && left.B == right.B
- && left.A == right.A;
+ return left.Rgba == right.Rgba;
}
///
@@ -159,10 +182,7 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Color left, Color right)
{
- return left.R != right.R
- && left.G != right.G
- && left.B != right.B
- && left.A != right.A;
+ return left.Rgba != right.Rgba;
}
///
@@ -245,7 +265,7 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
- this = Pack(ref vector);
+ this.Pack(ref vector);
}
///
@@ -265,10 +285,7 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Color other)
{
- return this.R == other.R
- && this.G == other.G
- && this.B == other.B
- && this.A == other.A;
+ return this.Rgba == other.Rgba;
}
///
@@ -308,12 +325,12 @@ namespace ImageSharp
}
///
- /// Packs a into a uint.
+ /// Packs a into a color returning a new instance as a result.
///
/// The vector containing the values to pack.
/// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Color Pack(ref Vector4 vector)
+ private static Color PackNew(ref Vector4 vector)
{
vector *= MaxBytes;
vector += Half;
@@ -322,31 +339,46 @@ namespace ImageSharp
return new Color((byte)vector.X, (byte)vector.Y, (byte)vector.Z, (byte)vector.W);
}
+ ///
+ /// Packs the four floats into a color.
+ ///
+ /// The x-component
+ /// The y-component
+ /// The z-component
+ /// The w-component
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void Pack(float x, float y, float z, float w)
+ {
+ Vector4 value = new Vector4(x, y, z, w);
+ this.Pack(ref value);
+ }
+
///
/// Packs a into a uint.
///
/// The vector containing the values to pack.
- /// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Color Pack(ref Vector3 vector)
+ private void Pack(ref Vector3 vector)
{
Vector4 value = new Vector4(vector, 1);
- return Pack(ref value);
+ this.Pack(ref value);
}
///
- /// Packs the four floats into a .
+ /// Packs a into a color.
///
- /// The x-component
- /// The y-component
- /// The z-component
- /// The w-component
- /// The
+ /// The vector containing the values to pack.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Color Pack(float x, float y, float z, float w)
+ private void Pack(ref Vector4 vector)
{
- Vector4 value = new Vector4(x, y, z, w);
- return Pack(ref value);
+ vector *= MaxBytes;
+ vector += Half;
+ vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
+
+ this.R = (byte)vector.X;
+ this.G = (byte)vector.Y;
+ this.B = (byte)vector.Z;
+ this.A = (byte)vector.W;
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs
index c9312eed1..c40abd934 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs
@@ -193,7 +193,7 @@ namespace ImageSharp.Tests
int pixelCount = left * top;
uint stepsPerPixel = (uint)(uint.MaxValue / pixelCount);
TColor c = default(TColor);
- Rgba32 t = new Rgba32(0);
+ Color t = new Color(0);
for (int x = left; x < right; x++)
for (int y = top; y < bottom; y++)