Browse Source

Inint remove packing from Color.

af/merge-core
James Jackson-South 9 years ago
parent
commit
a63dae887f
  1. 226
      src/ImageSharp/Colors/Color.cs
  2. 28
      src/ImageSharp/Colors/ColorTransforms.cs
  3. 398
      src/ImageSharp/Colors/PackedPixel/Rgba32.cs
  4. 10
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs

226
src/ImageSharp/Colors/Color.cs

@ -5,10 +5,9 @@
namespace ImageSharp namespace ImageSharp
{ {
using System;
using System.Globalization;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <summary> /// <summary>
/// Packed 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.
@ -18,8 +17,33 @@ namespace ImageSharp
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations. /// as it avoids the need to create new values for modification operations.
/// </remarks> /// </remarks>
public partial struct Color : IPixel<Color>, IPackedVector<uint> [StructLayout(LayoutKind.Explicit)]
public partial struct Color : IPixel<Color>
{ {
/// <summary>
/// Gets or sets the red component.
/// </summary>
[FieldOffset(0)]
public byte R;
/// <summary>
/// Gets or sets the green component.
/// </summary>
[FieldOffset(1)]
public byte G;
/// <summary>
/// Gets or sets the blue component.
/// </summary>
[FieldOffset(2)]
public byte B;
/// <summary>
/// Gets or sets the alpha component.
/// </summary>
[FieldOffset(3)]
public byte A;
/// <summary> /// <summary>
/// The shift count for the red component /// The shift count for the red component
/// </summary> /// </summary>
@ -50,11 +74,6 @@ namespace ImageSharp
/// </summary> /// </summary>
private static readonly Vector4 Half = new Vector4(0.5F); private static readonly Vector4 Half = new Vector4(0.5F);
/// <summary>
/// The packed value.
/// </summary>
private uint packedValue;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Color"/> struct. /// Initializes a new instance of the <see cref="Color"/> struct.
/// </summary> /// </summary>
@ -63,8 +82,12 @@ namespace ImageSharp
/// <param name="b">The blue component.</param> /// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param> /// <param name="a">The alpha component.</param>
public Color(byte r, byte g, byte b, byte a = 255) public Color(byte r, byte g, byte b, byte a = 255)
: this()
{ {
this.packedValue = Pack(r, g, b, a); this.R = r;
this.G = g;
this.B = b;
this.A = a;
} }
/// <summary> /// <summary>
@ -75,8 +98,9 @@ namespace ImageSharp
/// <param name="b">The blue component.</param> /// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param> /// <param name="a">The alpha component.</param>
public Color(float r, float g, float b, float a = 1) public Color(float r, float g, float b, float a = 1)
: this()
{ {
this.packedValue = Pack(r, g, b, a); this = Pack(r, g, b, a);
} }
/// <summary> /// <summary>
@ -86,8 +110,9 @@ namespace ImageSharp
/// The vector containing the components for the packed vector. /// The vector containing the components for the packed vector.
/// </param> /// </param>
public Color(Vector3 vector) public Color(Vector3 vector)
: this()
{ {
this.packedValue = Pack(ref vector); this = Pack(ref vector);
} }
/// <summary> /// <summary>
@ -97,105 +122,9 @@ namespace ImageSharp
/// The vector containing the components for the packed vector. /// The vector containing the components for the packed vector.
/// </param> /// </param>
public Color(Vector4 vector) public Color(Vector4 vector)
: this()
{ {
this.packedValue = Pack(ref vector); this = Pack(ref vector);
}
/// <summary>
/// Initializes a new instance of the <see cref="Color"/> struct.
/// </summary>
/// <param name="packed">
/// The packed value.
/// </param>
public Color(uint packed)
{
this.packedValue = packed;
}
/// <summary>
/// Gets or sets the red component.
/// </summary>
public byte R
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (byte)(this.packedValue >> RedShift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.packedValue = this.packedValue & 0xFFFFFF00 | (uint)value << RedShift;
}
}
/// <summary>
/// Gets or sets the green component.
/// </summary>
public byte G
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (byte)(this.packedValue >> GreenShift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << GreenShift;
}
}
/// <summary>
/// Gets or sets the blue component.
/// </summary>
public byte B
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (byte)(this.packedValue >> BlueShift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << BlueShift;
}
}
/// <summary>
/// Gets or sets the alpha component.
/// </summary>
public byte A
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (byte)(this.packedValue >> AlphaShift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << AlphaShift;
}
}
/// <inheritdoc/>
public uint PackedValue
{
get
{
return this.packedValue;
}
set
{
this.packedValue = value;
}
} }
/// <summary> /// <summary>
@ -213,7 +142,10 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Color left, Color right) public static bool operator ==(Color left, Color right)
{ {
return left.packedValue == right.packedValue; return left.R == right.R
&& left.G == right.G
&& left.B == right.B
&& left.A == right.A;
} }
/// <summary> /// <summary>
@ -227,7 +159,10 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Color left, Color right) public static bool operator !=(Color left, Color right)
{ {
return left.packedValue != right.packedValue; return left.R != right.R
&& left.G != right.G
&& left.B != right.B
&& left.A != right.A;
} }
/// <summary> /// <summary>
@ -246,13 +181,16 @@ namespace ImageSharp
} }
/// <inheritdoc /> /// <inheritdoc />
public BulkPixelOperations<Color> CreateBulkOperations() => new Color.BulkOperations(); public BulkPixelOperations<Color> CreateBulkOperations() => new BulkOperations();
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w) public void PackFromBytes(byte x, byte y, byte z, byte w)
{ {
this.packedValue = Pack(x, y, z, w); this.R = x;
this.G = y;
this.B = z;
this.A = w;
} }
/// <summary> /// <summary>
@ -307,7 +245,7 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector) public void PackFromVector4(Vector4 vector)
{ {
this.packedValue = Pack(ref vector); this = Pack(ref vector);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -327,7 +265,10 @@ namespace ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Color other) public bool Equals(Color other)
{ {
return this.packedValue == other.packedValue; return this.R == other.R
&& this.G == other.G
&& this.B == other.B
&& this.A == other.A;
} }
/// <summary> /// <summary>
@ -342,33 +283,52 @@ namespace ImageSharp
/// <inheritdoc/> /// <inheritdoc/>
public override int GetHashCode() public override int GetHashCode()
{ {
return this.packedValue.GetHashCode(); unchecked
{
int hashCode = this.R.GetHashCode();
hashCode = (hashCode * 397) ^ this.G.GetHashCode();
hashCode = (hashCode * 397) ^ this.B.GetHashCode();
hashCode = (hashCode * 397) ^ this.A.GetHashCode();
return hashCode;
}
}
/// <summary>
/// Packs the four floats into a <see cref="uint"/>.
/// </summary>
/// <param name="x">The x-component</param>
/// <param name="y">The y-component</param>
/// <param name="z">The z-component</param>
/// <param name="w">The w-component</param>
/// <returns>The <see cref="uint"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(byte x, byte y, byte z, byte w)
{
return (uint)(x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift);
} }
/// <summary> /// <summary>
/// Packs a <see cref="Vector4"/> into a uint. /// Packs a <see cref="Vector4"/> into a uint.
/// </summary> /// </summary>
/// <param name="vector">The vector containing the values to pack.</param> /// <param name="vector">The vector containing the values to pack.</param>
/// <returns>The <see cref="uint"/> containing the packed values.</returns> /// <returns>The <see cref="Color"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(ref Vector4 vector) private static Color Pack(ref Vector4 vector)
{ {
vector *= MaxBytes; vector *= MaxBytes;
vector += Half; vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return (uint)(((byte)vector.X << RedShift)
| ((byte)vector.Y << GreenShift) return new Color((byte)vector.X, (byte)vector.Y, (byte)vector.Z, (byte)vector.W);
| ((byte)vector.Z << BlueShift)
| (byte)vector.W << AlphaShift);
} }
/// <summary> /// <summary>
/// Packs a <see cref="Vector3"/> into a uint. /// Packs a <see cref="Vector3"/> into a uint.
/// </summary> /// </summary>
/// <param name="vector">The vector containing the values to pack.</param> /// <param name="vector">The vector containing the values to pack.</param>
/// <returns>The <see cref="uint"/> containing the packed values.</returns> /// <returns>The <see cref="Color"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(ref Vector3 vector) private static Color Pack(ref Vector3 vector)
{ {
Vector4 value = new Vector4(vector, 1); Vector4 value = new Vector4(vector, 1);
return Pack(ref value); return Pack(ref value);
@ -381,26 +341,12 @@ namespace ImageSharp
/// <param name="y">The y-component</param> /// <param name="y">The y-component</param>
/// <param name="z">The z-component</param> /// <param name="z">The z-component</param>
/// <param name="w">The w-component</param> /// <param name="w">The w-component</param>
/// <returns>The <see cref="uint"/></returns> /// <returns>The <see cref="Color"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y, float z, float w) private static Color Pack(float x, float y, float z, float w)
{ {
Vector4 value = new Vector4(x, y, z, w); Vector4 value = new Vector4(x, y, z, w);
return Pack(ref value); return Pack(ref value);
} }
/// <summary>
/// Packs the four floats into a <see cref="uint"/>.
/// </summary>
/// <param name="x">The x-component</param>
/// <param name="y">The y-component</param>
/// <param name="z">The z-component</param>
/// <param name="w">The w-component</param>
/// <returns>The <see cref="uint"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(byte x, byte y, byte z, byte w)
{
return (uint)(x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift);
}
} }
} }

28
src/ImageSharp/Colors/ColorTransforms.cs

@ -28,7 +28,7 @@ namespace ImageSharp
public static Color operator +(Color left, Color right) public static Color operator +(Color left, Color right)
{ {
Vector4 add = left.ToVector4() + right.ToVector4(); Vector4 add = left.ToVector4() + right.ToVector4();
return new Color(Pack(ref add)); return Pack(ref add);
} }
/// <summary> /// <summary>
@ -42,7 +42,7 @@ namespace ImageSharp
public static Color operator -(Color left, Color right) public static Color operator -(Color left, Color right)
{ {
Vector4 sub = left.ToVector4() - right.ToVector4(); Vector4 sub = left.ToVector4() - right.ToVector4();
return new Color(Pack(ref sub)); return Pack(ref sub);
} }
/// <summary> /// <summary>
@ -56,7 +56,7 @@ namespace ImageSharp
public static Color Normal(Color backdrop, Color source) public static Color Normal(Color backdrop, Color source)
{ {
Vector4 normal = Vector4BlendTransforms.Normal(backdrop.ToVector4(), source.ToVector4()); Vector4 normal = Vector4BlendTransforms.Normal(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref normal)); return Pack(ref normal);
} }
/// <summary> /// <summary>
@ -76,7 +76,7 @@ namespace ImageSharp
public static Color Multiply(Color backdrop, Color source) public static Color Multiply(Color backdrop, Color source)
{ {
Vector4 multiply = Vector4BlendTransforms.Multiply(backdrop.ToVector4(), source.ToVector4()); Vector4 multiply = Vector4BlendTransforms.Multiply(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref multiply)); return Pack(ref multiply);
} }
/// <summary> /// <summary>
@ -95,7 +95,7 @@ namespace ImageSharp
public static Color Screen(Color backdrop, Color source) public static Color Screen(Color backdrop, Color source)
{ {
Vector4 subtract = Vector4BlendTransforms.Screen(backdrop.ToVector4(), source.ToVector4()); Vector4 subtract = Vector4BlendTransforms.Screen(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref subtract)); return Pack(ref subtract);
} }
/// <summary> /// <summary>
@ -110,7 +110,7 @@ namespace ImageSharp
public static Color HardLight(Color backdrop, Color source) public static Color HardLight(Color backdrop, Color source)
{ {
Vector4 hardlight = Vector4BlendTransforms.HardLight(backdrop.ToVector4(), source.ToVector4()); Vector4 hardlight = Vector4BlendTransforms.HardLight(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref hardlight)); return Pack(ref hardlight);
} }
/// <summary> /// <summary>
@ -129,7 +129,7 @@ namespace ImageSharp
public static Color Overlay(Color backdrop, Color source) public static Color Overlay(Color backdrop, Color source)
{ {
Vector4 overlay = Vector4BlendTransforms.Overlay(backdrop.ToVector4(), source.ToVector4()); Vector4 overlay = Vector4BlendTransforms.Overlay(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref overlay)); return Pack(ref overlay);
} }
/// <summary> /// <summary>
@ -144,7 +144,7 @@ namespace ImageSharp
public static Color Darken(Color backdrop, Color source) public static Color Darken(Color backdrop, Color source)
{ {
Vector4 darken = Vector4BlendTransforms.Darken(backdrop.ToVector4(), source.ToVector4()); Vector4 darken = Vector4BlendTransforms.Darken(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref darken)); return Pack(ref darken);
} }
/// <summary> /// <summary>
@ -159,7 +159,7 @@ namespace ImageSharp
public static Color Lighten(Color backdrop, Color source) public static Color Lighten(Color backdrop, Color source)
{ {
Vector4 lighten = Vector4BlendTransforms.Lighten(backdrop.ToVector4(), source.ToVector4()); Vector4 lighten = Vector4BlendTransforms.Lighten(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref lighten)); return Pack(ref lighten);
} }
/// <summary> /// <summary>
@ -174,7 +174,7 @@ namespace ImageSharp
public static Color SoftLight(Color backdrop, Color source) public static Color SoftLight(Color backdrop, Color source)
{ {
Vector4 softlight = Vector4BlendTransforms.SoftLight(backdrop.ToVector4(), source.ToVector4()); Vector4 softlight = Vector4BlendTransforms.SoftLight(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref softlight)); return Pack(ref softlight);
} }
/// <summary> /// <summary>
@ -188,7 +188,7 @@ namespace ImageSharp
public static Color ColorDodge(Color backdrop, Color source) public static Color ColorDodge(Color backdrop, Color source)
{ {
Vector4 dodge = Vector4BlendTransforms.Dodge(backdrop.ToVector4(), source.ToVector4()); Vector4 dodge = Vector4BlendTransforms.Dodge(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref dodge)); return Pack(ref dodge);
} }
/// <summary> /// <summary>
@ -202,7 +202,7 @@ namespace ImageSharp
public static Color ColorBurn(Color backdrop, Color source) public static Color ColorBurn(Color backdrop, Color source)
{ {
Vector4 burn = Vector4BlendTransforms.Burn(backdrop.ToVector4(), source.ToVector4()); Vector4 burn = Vector4BlendTransforms.Burn(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref burn)); return Pack(ref burn);
} }
/// <summary> /// <summary>
@ -217,7 +217,7 @@ namespace ImageSharp
public static Color Difference(Color backdrop, Color source) public static Color Difference(Color backdrop, Color source)
{ {
Vector4 difference = Vector4BlendTransforms.Difference(backdrop.ToVector4(), source.ToVector4()); Vector4 difference = Vector4BlendTransforms.Difference(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref difference)); return Pack(ref difference);
} }
/// <summary> /// <summary>
@ -232,7 +232,7 @@ namespace ImageSharp
public static Color Exclusion(Color backdrop, Color source) public static Color Exclusion(Color backdrop, Color source)
{ {
Vector4 exclusion = Vector4BlendTransforms.Exclusion(backdrop.ToVector4(), source.ToVector4()); Vector4 exclusion = Vector4BlendTransforms.Exclusion(backdrop.ToVector4(), source.ToVector4());
return new Color(Pack(ref exclusion)); return Pack(ref exclusion);
} }
/// <summary> /// <summary>

398
src/ImageSharp/Colors/PackedPixel/Rgba32.cs

@ -0,0 +1,398 @@
// <copyright file="Rgba32.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System.Numerics;
using System.Runtime.CompilerServices;
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public struct Rgba32 : IPixel<Rgba32>, IPackedVector<uint>
{
/// <summary>
/// The shift count for the red component
/// </summary>
private const int RedShift = 0;
/// <summary>
/// The shift count for the green component
/// </summary>
private const int GreenShift = 8;
/// <summary>
/// The shift count for the blue component
/// </summary>
private const int BlueShift = 16;
/// <summary>
/// The shift count for the alpha component
/// </summary>
private const int AlphaShift = 24;
/// <summary>
/// The maximum byte value.
/// </summary>
private static readonly Vector4 MaxBytes = new Vector4(255);
/// <summary>
/// The half vector value.
/// </summary>
private static readonly Vector4 Half = new Vector4(0.5F);
/// <summary>
/// The packed value.
/// </summary>
private uint packedValue;
/// <summary>
/// Initializes a new instance of the <see cref="Rgba32"/> struct.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
public Rgba32(byte r, byte g, byte b, byte a = 255)
{
this.packedValue = Pack(r, g, b, a);
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgba32"/> struct.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
public Rgba32(float r, float g, float b, float a = 1)
{
this.packedValue = Pack(r, g, b, a);
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgba32"/> struct.
/// </summary>
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
public Rgba32(Vector3 vector)
{
this.packedValue = Pack(ref vector);
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgba32"/> struct.
/// </summary>
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
public Rgba32(Vector4 vector)
{
this.packedValue = Pack(ref vector);
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgba32"/> struct.
/// </summary>
/// <param name="packed">
/// The packed value.
/// </param>
public Rgba32(uint packed)
{
this.packedValue = packed;
}
/// <summary>
/// Gets or sets the red component.
/// </summary>
public byte R
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (byte)(this.packedValue >> RedShift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.packedValue = this.packedValue & 0xFFFFFF00 | (uint)value << RedShift;
}
}
/// <summary>
/// Gets or sets the green component.
/// </summary>
public byte G
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (byte)(this.packedValue >> GreenShift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << GreenShift;
}
}
/// <summary>
/// Gets or sets the blue component.
/// </summary>
public byte B
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (byte)(this.packedValue >> BlueShift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << BlueShift;
}
}
/// <summary>
/// Gets or sets the alpha component.
/// </summary>
public byte A
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return (byte)(this.packedValue >> AlphaShift);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << AlphaShift;
}
}
/// <inheritdoc/>
public uint PackedValue
{
get => this.packedValue;
set => this.packedValue = value;
}
/// <summary>
/// Compares two <see cref="Rgba32"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="Rgba32"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="Rgba32"/> on the right side of the operand.
/// </param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Rgba32 left, Rgba32 right)
{
return left.packedValue == right.packedValue;
}
/// <summary>
/// Compares two <see cref="Rgba32"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Rgba32"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Rgba32"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rgba32 left, Rgba32 right)
{
return left.packedValue != right.packedValue;
}
/// <summary>
/// Creates a new instance of the <see cref="Rgba32"/> struct.
/// </summary>
/// <param name="hex">
/// The hexadecimal representation of the combined color components arranged
/// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax.
/// </param>
/// <returns>
/// The <see cref="Rgba32"/>.
/// </returns>
public static Rgba32 FromHex(string hex)
{
return ColorBuilder<Rgba32>.FromHex(hex);
}
/// <inheritdoc />
public BulkPixelOperations<Rgba32> CreateBulkOperations() => new BulkPixelOperations<Rgba32>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
{
this.packedValue = Pack(x, y, z, w);
}
/// <summary>
/// Converts the value of this instance to a hexadecimal string.
/// </summary>
/// <returns>A hexadecimal string representation of the value.</returns>
public string ToHex()
{
uint hexOrder = Pack(this.A, this.B, this.G, this.R);
return hexOrder.ToString("X8");
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
bytes[startIndex + 3] = this.A;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(byte[] bytes, int startIndex)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
bytes[startIndex + 3] = this.A;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.packedValue = Pack(ref vector);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return (obj is Rgba32) && this.Equals((Rgba32)obj);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rgba32 other)
{
return this.packedValue == other.packedValue;
}
/// <summary>
/// Gets a string representation of the packed vector.
/// </summary>
/// <returns>A string representation of the packed vector.</returns>
public override string ToString()
{
return this.ToVector4().ToString();
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.packedValue.GetHashCode();
}
/// <summary>
/// Packs a <see cref="Vector4"/> into a uint.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(ref Vector4 vector)
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return (uint)(((byte)vector.X << RedShift)
| ((byte)vector.Y << GreenShift)
| ((byte)vector.Z << BlueShift)
| (byte)vector.W << AlphaShift);
}
/// <summary>
/// Packs a <see cref="Vector3"/> into a uint.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(ref Vector3 vector)
{
Vector4 value = new Vector4(vector, 1);
return Pack(ref value);
}
/// <summary>
/// Packs the four floats into a <see cref="uint"/>.
/// </summary>
/// <param name="x">The x-component</param>
/// <param name="y">The y-component</param>
/// <param name="z">The z-component</param>
/// <param name="w">The w-component</param>
/// <returns>The <see cref="uint"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y, float z, float w)
{
Vector4 value = new Vector4(x, y, z, w);
return Pack(ref value);
}
/// <summary>
/// Packs the four floats into a <see cref="uint"/>.
/// </summary>
/// <param name="x">The x-component</param>
/// <param name="y">The y-component</param>
/// <param name="z">The z-component</param>
/// <param name="w">The w-component</param>
/// <returns>The <see cref="uint"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(byte x, byte y, byte z, byte w)
{
return (uint)(x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift);
}
}
}

10
tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs

@ -61,7 +61,7 @@ namespace ImageSharp.Tests
BlackWhiteChecker(pixels); // top left BlackWhiteChecker(pixels); // top left
VirticalBars(pixels); // top right VirticalBars(pixels); // top right
TransparentGradients(pixels); // bottom left TransparentGradients(pixels); // bottom left
Rainbow(pixels); // bottom right Rainbow(pixels); // bottom right
} }
} }
/// <summary> /// <summary>
@ -70,7 +70,7 @@ namespace ImageSharp.Tests
/// <param name="pixels"></param> /// <param name="pixels"></param>
private static void VirticalBars(PixelAccessor<TColor> pixels) private static void VirticalBars(PixelAccessor<TColor> pixels)
{ {
// topLeft // topLeft
int left = pixels.Width / 2; int left = pixels.Width / 2;
int right = pixels.Width; int right = pixels.Width;
int top = 0; int top = 0;
@ -101,7 +101,7 @@ namespace ImageSharp.Tests
/// <param name="pixels"></param> /// <param name="pixels"></param>
private static void BlackWhiteChecker(PixelAccessor<TColor> pixels) private static void BlackWhiteChecker(PixelAccessor<TColor> pixels)
{ {
// topLeft // topLeft
int left = 0; int left = 0;
int right = pixels.Width / 2; int right = pixels.Width / 2;
int top = 0; int top = 0;
@ -140,7 +140,7 @@ namespace ImageSharp.Tests
/// <param name="pixels"></param> /// <param name="pixels"></param>
private static void TransparentGradients(PixelAccessor<TColor> pixels) private static void TransparentGradients(PixelAccessor<TColor> pixels)
{ {
// topLeft // topLeft
int left = 0; int left = 0;
int right = pixels.Width / 2; int right = pixels.Width / 2;
int top = pixels.Height / 2; int top = pixels.Height / 2;
@ -193,7 +193,7 @@ namespace ImageSharp.Tests
int pixelCount = left * top; int pixelCount = left * top;
uint stepsPerPixel = (uint)(uint.MaxValue / pixelCount); uint stepsPerPixel = (uint)(uint.MaxValue / pixelCount);
TColor c = default(TColor); TColor c = default(TColor);
Color t = new Color(0); Rgba32 t = new Rgba32(0);
for (int x = left; x < right; x++) for (int x = left; x < right; x++)
for (int y = top; y < bottom; y++) for (int y = top; y < bottom; y++)

Loading…
Cancel
Save