From 0be847e373158d6039d0d2851a42a3b7c2470fc5 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 24 Mar 2017 18:36:52 +1100 Subject: [PATCH] Remove all current colorspaces --- src/ImageSharp/Colors/ColorspaceTransforms.cs | 288 ---------- src/ImageSharp/Colors/Spaces/Bgra32.cs | 166 ------ src/ImageSharp/Colors/Spaces/CieLab.cs | 187 ------- src/ImageSharp/Colors/Spaces/CieXyz.cs | 168 ------ src/ImageSharp/Colors/Spaces/Cmyk.cs | 189 ------- src/ImageSharp/Colors/Spaces/Hsl.cs | 207 -------- src/ImageSharp/Colors/Spaces/Hsv.cs | 200 ------- .../Colors/Spaces/IAlmostEquatable.cs | 30 -- src/ImageSharp/Colors/Spaces/YCbCr.cs | 165 ------ .../Colors/ColorConversionTests.cs | 493 ------------------ .../Colors/ColorDefinitionTests.cs | 3 - .../Colors/ColorEqualityTests.cs | 216 +------- 12 files changed, 16 insertions(+), 2296 deletions(-) delete mode 100644 src/ImageSharp/Colors/ColorspaceTransforms.cs delete mode 100644 src/ImageSharp/Colors/Spaces/Bgra32.cs delete mode 100644 src/ImageSharp/Colors/Spaces/CieLab.cs delete mode 100644 src/ImageSharp/Colors/Spaces/CieXyz.cs delete mode 100644 src/ImageSharp/Colors/Spaces/Cmyk.cs delete mode 100644 src/ImageSharp/Colors/Spaces/Hsl.cs delete mode 100644 src/ImageSharp/Colors/Spaces/Hsv.cs delete mode 100644 src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs delete mode 100644 src/ImageSharp/Colors/Spaces/YCbCr.cs delete mode 100644 tests/ImageSharp.Tests/Colors/ColorConversionTests.cs diff --git a/src/ImageSharp/Colors/ColorspaceTransforms.cs b/src/ImageSharp/Colors/ColorspaceTransforms.cs deleted file mode 100644 index cda7022705..0000000000 --- a/src/ImageSharp/Colors/ColorspaceTransforms.cs +++ /dev/null @@ -1,288 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using System; - using System.Numerics; - using Colors.Spaces; - - /// - /// Packed vector 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. - /// - /// - /// 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. - /// - public partial struct Color - { - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(Bgra32 color) - { - return new Color(color.R, color.G, color.B, color.A); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(Cmyk cmykColor) - { - float r = (1 - cmykColor.C) * (1 - cmykColor.K); - float g = (1 - cmykColor.M) * (1 - cmykColor.K); - float b = (1 - cmykColor.Y) * (1 - cmykColor.K); - return new Color(r, g, b, 1); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(YCbCr color) - { - float y = color.Y; - float cb = color.Cb - 128; - float cr = color.Cr - 128; - - byte r = (byte)(y + (1.402F * cr)).Clamp(0, 255); - byte g = (byte)(y - (0.34414F * cb) - (0.71414F * cr)).Clamp(0, 255); - byte b = (byte)(y + (1.772F * cb)).Clamp(0, 255); - - return new Color(r, g, b); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(CieXyz color) - { - float x = color.X / 100F; - float y = color.Y / 100F; - float z = color.Z / 100F; - - // Then XYZ to RGB (multiplication by 100 was done above already) - float r = (x * 3.2406F) + (y * -1.5372F) + (z * -0.4986F); - float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F); - float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F); - - Vector4 vector = new Vector4(r, g, b, 1).Compress(); - return new Color(vector); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(Hsv color) - { - float s = color.S; - float v = color.V; - - if (Math.Abs(s) < Constants.Epsilon) - { - return new Color(v, v, v, 1); - } - - float h = (Math.Abs(color.H - 360) < Constants.Epsilon) ? 0 : color.H / 60; - int i = (int)Math.Truncate(h); - float f = h - i; - - float p = v * (1.0F - s); - float q = v * (1.0F - (s * f)); - float t = v * (1.0F - (s * (1.0F - f))); - - float r, g, b; - switch (i) - { - case 0: - r = v; - g = t; - b = p; - break; - - case 1: - r = q; - g = v; - b = p; - break; - - case 2: - r = p; - g = v; - b = t; - break; - - case 3: - r = p; - g = q; - b = v; - break; - - case 4: - r = t; - g = p; - b = v; - break; - - default: - r = v; - g = p; - b = q; - break; - } - - return new Color(r, g, b, 1); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(Hsl color) - { - float rangedH = color.H / 360F; - float r = 0; - float g = 0; - float b = 0; - float s = color.S; - float l = color.L; - - if (Math.Abs(l) > Constants.Epsilon) - { - if (Math.Abs(s) < Constants.Epsilon) - { - r = g = b = l; - } - else - { - float temp2 = (l < 0.5f) ? l * (1f + s) : l + s - (l * s); - float temp1 = (2f * l) - temp2; - - r = GetColorComponent(temp1, temp2, rangedH + 0.3333333F); - g = GetColorComponent(temp1, temp2, rangedH); - b = GetColorComponent(temp1, temp2, rangedH - 0.3333333F); - } - } - - return new Color(r, g, b, 1); - } - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Color(CieLab cieLabColor) - { - // First convert back to XYZ... - float y = (cieLabColor.L + 16F) / 116F; - float x = (cieLabColor.A / 500F) + y; - float z = y - (cieLabColor.B / 200F); - - float x3 = x * x * x; - float y3 = y * y * y; - float z3 = z * z * z; - - x = x3 > 0.008856F ? x3 : (x - 0.137931F) / 7.787F; - y = (cieLabColor.L > 7.999625F) ? y3 : (cieLabColor.L / 903.3F); - z = (z3 > 0.008856F) ? z3 : (z - 0.137931F) / 7.787F; - - x *= 0.95047F; - z *= 1.08883F; - - // Then XYZ to RGB (multiplication by 100 was done above already) - float r = (x * 3.2406F) + (y * -1.5372F) + (z * -0.4986F); - float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F); - float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F); - - return new Color(new Vector4(r, g, b, 1F).Compress()); - } - - /// - /// Gets the color component from the given values. - /// - /// The first value. - /// The second value. - /// The third value. - /// - /// The . - /// - private static float GetColorComponent(float first, float second, float third) - { - third = MoveIntoRange(third); - if (third < 0.1666667F) - { - return first + ((second - first) * 6.0f * third); - } - - if (third < 0.5) - { - return second; - } - - if (third < 0.6666667F) - { - return first + ((second - first) * (0.6666667F - third) * 6.0f); - } - - return first; - } - - /// - /// Moves the specific value within the acceptable range for - /// conversion. - /// Used for converting colors to this type. - /// - /// The value to shift. - /// - /// The . - /// - private static float MoveIntoRange(float value) - { - if (value < 0.0) - { - value += 1.0f; - } - else if (value > 1.0) - { - value -= 1.0f; - } - - return value; - } - } -} diff --git a/src/ImageSharp/Colors/Spaces/Bgra32.cs b/src/ImageSharp/Colors/Spaces/Bgra32.cs deleted file mode 100644 index cbd1d61194..0000000000 --- a/src/ImageSharp/Colors/Spaces/Bgra32.cs +++ /dev/null @@ -1,166 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Colors.Spaces -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an BGRA (blue, green, red, alpha) color. - /// - public struct Bgra32 : IEquatable - { - /// - /// Represents a 32 bit that has B, G, R, and A values set to zero. - /// - public static readonly Bgra32 Empty = default(Bgra32); - - /// - /// Min range used for clamping - /// - private static readonly Vector4 VectorMin = Vector4.Zero; - - /// - /// Max range used for clamping - /// - private static readonly Vector4 VectorMax = new Vector4(255); - - /// - /// The backing vector for SIMD support. - /// - private readonly Vector4 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The blue component of this . - /// The green component of this . - /// The red component of this . - /// The alpha component of this . - public Bgra32(byte b, byte g, byte r, byte a = 255) - : this() - { - this.backingVector = Vector4.Clamp(new Vector4(b, g, r, a), VectorMin, VectorMax); - } - - /// - /// Gets the blue component of the color - /// - public byte B => (byte)this.backingVector.X; - - /// - /// Gets the green component of the color - /// - public byte G => (byte)this.backingVector.Y; - - /// - /// Gets the red component of the color - /// - public byte R => (byte)this.backingVector.Z; - - /// - /// Gets the alpha component of the color - /// - public byte A => (byte)this.backingVector.W; - - /// - /// Gets the integer representation of the color. - /// - public int Bgra => (this.R << 16) | (this.G << 8) | (this.B << 0) | (this.A << 24); - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator Bgra32(Color color) - { - return new Bgra32(color.B, color.G, color.R, color.A); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Bgra32 left, Bgra32 right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Bgra32 left, Bgra32 right) - { - return !left.Equals(right); - } - - /// - public override bool Equals(object obj) - { - if (obj is Bgra32) - { - Bgra32 color = (Bgra32)obj; - - return this.backingVector == color.backingVector; - } - - return false; - } - - /// - public override int GetHashCode() - { - return this.backingVector.GetHashCode(); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Bgra32 [ Empty ]"; - } - - return $"Bgra32 [ B={this.B}, G={this.G}, R={this.R}, A={this.A} ]"; - } - - /// - public bool Equals(Bgra32 other) - { - return this.backingVector.Equals(other.backingVector); - } - } -} diff --git a/src/ImageSharp/Colors/Spaces/CieLab.cs b/src/ImageSharp/Colors/Spaces/CieLab.cs deleted file mode 100644 index ecc1bca5ad..0000000000 --- a/src/ImageSharp/Colors/Spaces/CieLab.cs +++ /dev/null @@ -1,187 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Colors.Spaces -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an CIE LAB 1976 color. - /// - /// - public struct CieLab : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has L, A, B values set to zero. - /// - public static readonly CieLab Empty = default(CieLab); - - /// - /// Min range used for clamping - /// - private static readonly Vector3 VectorMin = new Vector3(0, -100, -100); - - /// - /// Max range used for clamping - /// - private static readonly Vector3 VectorMax = new Vector3(100); - - /// - /// The backing vector for SIMD support. - /// - private readonly Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The lightness dimension. - /// The a (green - magenta) component. - /// The b (blue - yellow) component. - public CieLab(float l, float a, float b) - : this() - { - this.backingVector = Vector3.Clamp(new Vector3(l, a, b), VectorMin, VectorMax); - } - - /// - /// Gets the lightness dimension. - /// A value ranging between 0 (black), 100 (diffuse white) or higher (specular white). - /// - public float L => this.backingVector.X; - - /// - /// Gets the a color component. - /// Negative is green, positive magenta. - /// - public float A => this.backingVector.Y; - - /// - /// Gets the b color component. - /// Negative is blue, positive is yellow - /// - public float B => this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator CieLab(Color color) - { - // First convert to CIE XYZ - Vector4 vector = color.ToVector4().Expand(); - float x = (vector.X * 0.4124F) + (vector.Y * 0.3576F) + (vector.Z * 0.1805F); - float y = (vector.X * 0.2126F) + (vector.Y * 0.7152F) + (vector.Z * 0.0722F); - float z = (vector.X * 0.0193F) + (vector.Y * 0.1192F) + (vector.Z * 0.9505F); - - // Now to LAB - x /= 0.95047F; - - // y /= 1F; - z /= 1.08883F; - - x = x > 0.008856F ? (float)Math.Pow(x, 0.3333333F) : ((903.3F * x) + 16F) / 116F; - y = y > 0.008856F ? (float)Math.Pow(y, 0.3333333F) : ((903.3F * y) + 16F) / 116F; - z = z > 0.008856F ? (float)Math.Pow(z, 0.3333333F) : ((903.3F * z) + 16F) / 116F; - - float l = Math.Max(0, (116F * y) - 16F); - float a = 500F * (x - y); - float b = 200F * (y - z); - - return new CieLab(l, a, b); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(CieLab left, CieLab right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(CieLab left, CieLab right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return this.backingVector.GetHashCode(); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "CieLab [Empty]"; - } - - return $"CieLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is CieLab) - { - return this.Equals((CieLab)obj); - } - - return false; - } - - /// - public bool Equals(CieLab other) - { - return this.backingVector.Equals(other.backingVector); - } - - /// - public bool AlmostEquals(CieLab other, float precision) - { - Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); - - return result.X <= precision - && result.Y <= precision - && result.Z <= precision; - } - } -} diff --git a/src/ImageSharp/Colors/Spaces/CieXyz.cs b/src/ImageSharp/Colors/Spaces/CieXyz.cs deleted file mode 100644 index 5bd1eac634..0000000000 --- a/src/ImageSharp/Colors/Spaces/CieXyz.cs +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Colors.Spaces -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an CIE 1931 color - /// - /// - public struct CieXyz : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has Y, Cb, and Cr values set to zero. - /// - public static readonly CieXyz Empty = default(CieXyz); - - /// - /// The backing vector for SIMD support. - /// - private readonly Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// X is a mix (a linear combination) of cone response curves chosen to be nonnegative - /// The y luminance component. - /// Z is quasi-equal to blue stimulation, or the S cone of the human eye. - public CieXyz(float x, float y, float z) - : this() - { - // Not clamping as documentation about this space seems to indicate "usual" ranges - this.backingVector = new Vector3(x, y, z); - } - - /// - /// Gets the Y luminance component. - /// A value ranging between 380 and 780. - /// - public float X => this.backingVector.X; - - /// - /// Gets the Cb chroma component. - /// A value ranging between 380 and 780. - /// - public float Y => this.backingVector.Y; - - /// - /// Gets the Cr chroma component. - /// A value ranging between 380 and 780. - /// - public float Z => this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator CieXyz(Color color) - { - Vector4 vector = color.ToVector4().Expand(); - - float x = (vector.X * 0.4124F) + (vector.Y * 0.3576F) + (vector.Z * 0.1805F); - float y = (vector.X * 0.2126F) + (vector.Y * 0.7152F) + (vector.Z * 0.0722F); - float z = (vector.X * 0.0193F) + (vector.Y * 0.1192F) + (vector.Z * 0.9505F); - - x *= 100F; - y *= 100F; - z *= 100F; - - return new CieXyz(x, y, z); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(CieXyz left, CieXyz right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(CieXyz left, CieXyz right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return this.backingVector.GetHashCode(); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "CieXyz [ Empty ]"; - } - - return $"CieXyz [ X={this.X:#0.##}, Y={this.Y:#0.##}, Z={this.Z:#0.##} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is CieXyz) - { - return this.Equals((CieXyz)obj); - } - - return false; - } - - /// - public bool Equals(CieXyz other) - { - return this.backingVector.Equals(other.backingVector); - } - - /// - public bool AlmostEquals(CieXyz other, float precision) - { - Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); - - return result.X <= precision - && result.Y <= precision - && result.Z <= precision; - } - } -} diff --git a/src/ImageSharp/Colors/Spaces/Cmyk.cs b/src/ImageSharp/Colors/Spaces/Cmyk.cs deleted file mode 100644 index 53618312c7..0000000000 --- a/src/ImageSharp/Colors/Spaces/Cmyk.cs +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Colors.Spaces -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an CMYK (cyan, magenta, yellow, keyline) color. - /// - public struct Cmyk : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has C, M, Y, and K values set to zero. - /// - public static readonly Cmyk Empty = default(Cmyk); - - /// - /// Min range used for clamping - /// - private static readonly Vector4 VectorMin = Vector4.Zero; - - /// - /// Max range used for clamping - /// - private static readonly Vector4 VectorMax = Vector4.One; - - /// - /// The backing vector for SIMD support. - /// - private readonly Vector4 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The cyan component. - /// The magenta component. - /// The yellow component. - /// The keyline black component. - public Cmyk(float c, float m, float y, float k) - : this() - { - this.backingVector = Vector4.Clamp(new Vector4(c, m, y, k), VectorMin, VectorMax); - } - - /// - /// Gets the cyan color component. - /// A value ranging between 0 and 1. - /// - public float C => this.backingVector.X; - - /// - /// Gets the magenta color component. - /// A value ranging between 0 and 1. - /// - public float M => this.backingVector.Y; - - /// - /// Gets the yellow color component. - /// A value ranging between 0 and 1. - /// - public float Y => this.backingVector.Z; - - /// - /// Gets the keyline black color component. - /// A value ranging between 0 and 1. - /// - public float K => this.backingVector.W; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator Cmyk(Color color) - { - float c = 1f - (color.R / 255F); - float m = 1f - (color.G / 255F); - float y = 1f - (color.B / 255F); - - float k = Math.Min(c, Math.Min(m, y)); - - if (Math.Abs(k - 1.0f) <= Constants.Epsilon) - { - return new Cmyk(0, 0, 0, 1); - } - - c = (c - k) / (1 - k); - m = (m - k) / (1 - k); - y = (y - k) / (1 - k); - - return new Cmyk(c, m, y, k); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Cmyk left, Cmyk right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Cmyk left, Cmyk right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return this.backingVector.GetHashCode(); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Cmyk [Empty]"; - } - - return $"Cmyk [ C={this.C:#0.##}, M={this.M:#0.##}, Y={this.Y:#0.##}, K={this.K:#0.##}]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Cmyk) - { - return this.Equals((Cmyk)obj); - } - - return false; - } - - /// - public bool Equals(Cmyk other) - { - return this.backingVector.Equals(other.backingVector); - } - - /// - public bool AlmostEquals(Cmyk other, float precision) - { - Vector4 result = Vector4.Abs(this.backingVector - other.backingVector); - - return result.X <= precision - && result.Y <= precision - && result.Z <= precision - && result.W <= precision; - } - } -} diff --git a/src/ImageSharp/Colors/Spaces/Hsl.cs b/src/ImageSharp/Colors/Spaces/Hsl.cs deleted file mode 100644 index 66f4a52bcc..0000000000 --- a/src/ImageSharp/Colors/Spaces/Hsl.cs +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Colors.Spaces -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents a Hsl (hue, saturation, lightness) color. - /// - public struct Hsl : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has H, S, and L values set to zero. - /// - public static readonly Hsl Empty = default(Hsl); - - /// - /// Min range used for clamping - /// - private static readonly Vector3 VectorMin = Vector3.Zero; - - /// - /// Max range used for clamping - /// - private static readonly Vector3 VectorMax = new Vector3(360, 1, 1); - - /// - /// The backing vector for SIMD support. - /// - private readonly Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The h hue component. - /// The s saturation component. - /// The l value (lightness) component. - public Hsl(float h, float s, float l) - { - this.backingVector = Vector3.Clamp(new Vector3(h, s, l), VectorMin, VectorMax); - } - - /// - /// Gets the hue component. - /// A value ranging between 0 and 360. - /// - public float H => this.backingVector.X; - - /// - /// Gets the saturation component. - /// A value ranging between 0 and 1. - /// - public float S => this.backingVector.Y; - - /// - /// Gets the lightness component. - /// A value ranging between 0 and 1. - /// - public float L => this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Hsl(Color color) - { - float r = color.R / 255F; - float g = color.G / 255F; - float b = color.B / 255F; - - float max = Math.Max(r, Math.Max(g, b)); - float min = Math.Min(r, Math.Min(g, b)); - float chroma = max - min; - float h = 0; - float s = 0; - float l = (max + min) / 2; - - if (Math.Abs(chroma) < Constants.Epsilon) - { - return new Hsl(0, s, l); - } - - if (Math.Abs(r - max) < Constants.Epsilon) - { - h = (g - b) / chroma; - } - else if (Math.Abs(g - max) < Constants.Epsilon) - { - h = 2 + ((b - r) / chroma); - } - else if (Math.Abs(b - max) < Constants.Epsilon) - { - h = 4 + ((r - g) / chroma); - } - - h *= 60; - if (h < 0.0) - { - h += 360; - } - - if (l <= .5f) - { - s = chroma / (max + min); - } - else - { - s = chroma / (2 - chroma); - } - - return new Hsl(h, s, l); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Hsl left, Hsl right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Hsl left, Hsl right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return this.backingVector.GetHashCode(); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Hsl [ Empty ]"; - } - - return $"Hsl [ H={this.H:#0.##}, S={this.S:#0.##}, L={this.L:#0.##} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Hsl) - { - return this.Equals((Hsl)obj); - } - - return false; - } - - /// - public bool Equals(Hsl other) - { - return this.backingVector.Equals(other.backingVector); - } - - /// - public bool AlmostEquals(Hsl other, float precision) - { - Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); - - return result.X <= precision - && result.Y <= precision - && result.Z <= precision; - } - } -} diff --git a/src/ImageSharp/Colors/Spaces/Hsv.cs b/src/ImageSharp/Colors/Spaces/Hsv.cs deleted file mode 100644 index b34977e2d9..0000000000 --- a/src/ImageSharp/Colors/Spaces/Hsv.cs +++ /dev/null @@ -1,200 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Colors.Spaces -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents a HSV (hue, saturation, value) color. Also known as HSB (hue, saturation, brightness). - /// - public struct Hsv : IEquatable, IAlmostEquatable - { - /// - /// Represents a that has H, S, and V values set to zero. - /// - public static readonly Hsv Empty = default(Hsv); - - /// - /// Min range used for clamping - /// - private static readonly Vector3 VectorMin = Vector3.Zero; - - /// - /// Max range used for clamping - /// - private static readonly Vector3 VectorMax = new Vector3(360, 1, 1); - - /// - /// The backing vector for SIMD support. - /// - private readonly Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The h hue component. - /// The s saturation component. - /// The v value (brightness) component. - public Hsv(float h, float s, float v) - { - this.backingVector = Vector3.Clamp(new Vector3(h, s, v), VectorMin, VectorMax); - } - - /// - /// Gets the hue component. - /// A value ranging between 0 and 360. - /// - public float H => this.backingVector.X; - - /// - /// Gets the saturation component. - /// A value ranging between 0 and 1. - /// - public float S => this.backingVector.Y; - - /// - /// Gets the value (brightness) component. - /// A value ranging between 0 and 1. - /// - public float V => this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// The instance of to convert. - /// - /// An instance of . - /// - public static implicit operator Hsv(Color color) - { - float r = color.R / 255F; - float g = color.G / 255F; - float b = color.B / 255F; - - float max = Math.Max(r, Math.Max(g, b)); - float min = Math.Min(r, Math.Min(g, b)); - float chroma = max - min; - float h = 0; - float s = 0; - float v = max; - - if (Math.Abs(chroma) < Constants.Epsilon) - { - return new Hsv(0, s, v); - } - - if (Math.Abs(r - max) < Constants.Epsilon) - { - h = (g - b) / chroma; - } - else if (Math.Abs(g - max) < Constants.Epsilon) - { - h = 2 + ((b - r) / chroma); - } - else if (Math.Abs(b - max) < Constants.Epsilon) - { - h = 4 + ((r - g) / chroma); - } - - h *= 60; - if (h < 0.0) - { - h += 360; - } - - s = chroma / v; - - return new Hsv(h, s, v); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Hsv left, Hsv right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Hsv left, Hsv right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return this.backingVector.GetHashCode(); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "Hsv [ Empty ]"; - } - - return $"Hsv [ H={this.H:#0.##}, S={this.S:#0.##}, V={this.V:#0.##} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is Hsv) - { - return this.Equals((Hsv)obj); - } - - return false; - } - - /// - public bool Equals(Hsv other) - { - return this.backingVector.Equals(other.backingVector); - } - - /// - public bool AlmostEquals(Hsv other, float precision) - { - Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); - - return result.X <= precision - && result.Y <= precision - && result.Z <= precision; - } - } -} diff --git a/src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs b/src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs deleted file mode 100644 index a2183d396c..0000000000 --- a/src/ImageSharp/Colors/Spaces/IAlmostEquatable.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Colors.Spaces -{ - using System; - - /// - /// Defines a generalized method that a value type or class implements to create - /// a type-specific method for determining approximate equality of instances. - /// - /// The type of objects to compare. - /// The object specifying the type to specify precision with. - public interface IAlmostEquatable - where TPrecision : struct, IComparable - { - /// - /// Indicates whether the current object is equal to another object of the same type - /// when compared to the specified precision level. - /// - /// An object to compare with this object. - /// The object specifying the level of precision. - /// - /// true if the current object is equal to the other parameter; otherwise, false. - /// - bool AlmostEquals(TColor other, TPrecision precision); - } -} diff --git a/src/ImageSharp/Colors/Spaces/YCbCr.cs b/src/ImageSharp/Colors/Spaces/YCbCr.cs deleted file mode 100644 index ef9f4462b1..0000000000 --- a/src/ImageSharp/Colors/Spaces/YCbCr.cs +++ /dev/null @@ -1,165 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Colors.Spaces -{ - using System; - using System.ComponentModel; - using System.Numerics; - - /// - /// Represents an YCbCr (luminance, blue chroma, red chroma) color conforming to the full range standard used in digital imaging systems. - /// - /// - public struct YCbCr : IEquatable - { - /// - /// Represents a that has Y, Cb, and Cr values set to zero. - /// - public static readonly YCbCr Empty = default(YCbCr); - - /// - /// Min range used for clamping - /// - private static readonly Vector3 VectorMin = Vector3.Zero; - - /// - /// Vector which is used in clamping to the max value - /// - private static readonly Vector3 VectorMax = new Vector3(255); - - /// - /// The backing vector for SIMD support. - /// - private readonly Vector3 backingVector; - - /// - /// Initializes a new instance of the struct. - /// - /// The y luminance component. - /// The cb chroma component. - /// The cr chroma component. - public YCbCr(byte y, byte cb, byte cr) - : this() - { - this.backingVector = Vector3.Clamp(new Vector3(y, cb, cr), VectorMin, VectorMax); - } - - /// - /// Gets the Y luminance component. - /// A value ranging between 0 and 255. - /// - public byte Y => (byte)this.backingVector.X; - - /// - /// Gets the Cb chroma component. - /// A value ranging between 0 and 255. - /// - public byte Cb => (byte)this.backingVector.Y; - - /// - /// Gets the Cr chroma component. - /// A value ranging between 0 and 255. - /// - public byte Cr => (byte)this.backingVector.Z; - - /// - /// Gets a value indicating whether this is empty. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); - - /// - /// Allows the implicit conversion of an instance of to a - /// . - /// - /// - /// The instance of to convert. - /// - /// - /// An instance of . - /// - public static implicit operator YCbCr(Color color) - { - byte r = color.R; - byte g = color.G; - byte b = color.B; - - byte y = (byte)((0.299F * r) + (0.587F * g) + (0.114F * b)); - byte cb = (byte)(128 + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b))); - byte cr = (byte)(128 + ((0.5F * r) - (0.418688F * g) - (0.081312F * b))); - - return new YCbCr(y, cb, cr); - } - - /// - /// Compares two objects for equality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(YCbCr left, YCbCr right) - { - return left.Equals(right); - } - - /// - /// Compares two objects for inequality. - /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(YCbCr left, YCbCr right) - { - return !left.Equals(right); - } - - /// - public override int GetHashCode() - { - return this.backingVector.GetHashCode(); - } - - /// - public override string ToString() - { - if (this.IsEmpty) - { - return "YCbCr [ Empty ]"; - } - - return $"YCbCr [ Y={this.Y}, Cb={this.Cb}, Cr={this.Cr} ]"; - } - - /// - public override bool Equals(object obj) - { - if (obj is YCbCr) - { - return this.Equals((YCbCr)obj); - } - - return false; - } - - /// - public bool Equals(YCbCr other) - { - return this.backingVector.Equals(other.backingVector); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Colors/ColorConversionTests.cs b/tests/ImageSharp.Tests/Colors/ColorConversionTests.cs deleted file mode 100644 index 9ed1c67a70..0000000000 --- a/tests/ImageSharp.Tests/Colors/ColorConversionTests.cs +++ /dev/null @@ -1,493 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System; - using System.Diagnostics.CodeAnalysis; - using ImageSharp.Colors.Spaces; - using Xunit; - - /// - /// Test conversion between the various color structs. - /// - /// - /// Output values have been compared with - /// and for accuracy. - /// - public class ColorConversionTests - { - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void ColorToYCbCr() - { - // White - Color color = Color.White; - YCbCr yCbCr = color; - - Assert.Equal(255, yCbCr.Y); - Assert.Equal(128, yCbCr.Cb); - Assert.Equal(128, yCbCr.Cr); - - // Black - Color color2 = Color.Black; - YCbCr yCbCr2 = color2; - Assert.Equal(0, yCbCr2.Y); - Assert.Equal(128, yCbCr2.Cb); - Assert.Equal(128, yCbCr2.Cr); - - // Gray - Color color3 = Color.Gray; - YCbCr yCbCr3 = color3; - Assert.Equal(128, yCbCr3.Y); - Assert.Equal(128, yCbCr3.Cb); - Assert.Equal(128, yCbCr3.Cr); - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void YCbCrToColor() - { - // White - YCbCr yCbCr = new YCbCr(255, 128, 128); - Color color = yCbCr; - - Assert.Equal(255, color.R); - Assert.Equal(255, color.G); - Assert.Equal(255, color.B); - Assert.Equal(255, color.A); - - // Black - YCbCr yCbCr2 = new YCbCr(0, 128, 128); - Color color2 = yCbCr2; - - Assert.Equal(0, color2.R); - Assert.Equal(0, color2.G); - Assert.Equal(0, color2.B); - Assert.Equal(255, color2.A); - - // Gray - YCbCr yCbCr3 = new YCbCr(128, 128, 128); - Color color3 = yCbCr3; - - Assert.Equal(128, color3.R); - Assert.Equal(128, color3.G); - Assert.Equal(128, color3.B); - Assert.Equal(255, color3.A); - } - - /// - /// Tests the implicit conversion from to . - /// Comparison values obtained from - /// http://colormine.org/convert/rgb-to-xyz - /// - [Fact] - public void ColorToCieXyz() - { - // White - Color color = Color.White; - CieXyz ciexyz = color; - - Assert.Equal(95.05f, ciexyz.X, 3); - Assert.Equal(100.0f, ciexyz.Y, 3); - Assert.Equal(108.900f, ciexyz.Z, 3); - - // Black - Color color2 = Color.Black; - CieXyz ciexyz2 = color2; - Assert.Equal(0, ciexyz2.X, 3); - Assert.Equal(0, ciexyz2.Y, 3); - Assert.Equal(0, ciexyz2.Z, 3); - - // Gray - Color color3 = Color.Gray; - CieXyz ciexyz3 = color3; - Assert.Equal(20.518, ciexyz3.X, 3); - Assert.Equal(21.586, ciexyz3.Y, 3); - Assert.Equal(23.507, ciexyz3.Z, 3); - - // Cyan - Color color4 = Color.Cyan; - CieXyz ciexyz4 = color4; - Assert.Equal(53.810f, ciexyz4.X, 3); - Assert.Equal(78.740f, ciexyz4.Y, 3); - Assert.Equal(106.970f, ciexyz4.Z, 3); - } - - /// - /// Tests the implicit conversion from to . - /// Comparison values obtained from - /// http://colormine.org/convert/rgb-to-xyz - /// - [Fact] - public void CieXyzToColor() - { - // Dark moderate pink. - CieXyz ciexyz = new CieXyz(13.337f, 9.297f, 14.727f); - Color color = ciexyz; - - Assert.Equal(128, color.R); - Assert.Equal(64, color.G); - Assert.Equal(106, color.B); - - // Ochre - CieXyz ciexyz2 = new CieXyz(31.787f, 26.147f, 4.885f); - Color color2 = ciexyz2; - - Assert.Equal(204, color2.R); - Assert.Equal(119, color2.G); - Assert.Equal(34, color2.B); - - // Black - CieXyz ciexyz3 = new CieXyz(0, 0, 0); - Color color3 = ciexyz3; - - Assert.Equal(0, color3.R); - Assert.Equal(0, color3.G); - Assert.Equal(0, color3.B); - - //// Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // CieXyz ciexyz4 = color4; - // Assert.Equal(color4, (Color)ciexyz4); - //} - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void ColorToHsv() - { - // Black - Color b = Color.Black; - Hsv h = b; - - Assert.Equal(0, h.H, 1); - Assert.Equal(0, h.S, 1); - Assert.Equal(0, h.V, 1); - - // White - Color color = Color.White; - Hsv hsv = color; - - Assert.Equal(0f, hsv.H, 1); - Assert.Equal(0f, hsv.S, 1); - Assert.Equal(1f, hsv.V, 1); - - // Dark moderate pink. - Color color2 = new Color(128, 64, 106); - Hsv hsv2 = color2; - - Assert.Equal(320.6f, hsv2.H, 1); - Assert.Equal(0.5f, hsv2.S, 1); - Assert.Equal(0.502f, hsv2.V, 2); - - // Ochre. - Color color3 = new Color(204, 119, 34); - Hsv hsv3 = color3; - - Assert.Equal(30f, hsv3.H, 1); - Assert.Equal(0.833f, hsv3.S, 3); - Assert.Equal(0.8f, hsv3.V, 1); - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - public void HsvToColor() - { - // Dark moderate pink. - Hsv hsv = new Hsv(320.6f, 0.5f, 0.502f); - Color color = hsv; - - Assert.Equal(color.R, 128); - Assert.Equal(color.G, 64); - Assert.Equal(color.B, 106); - - // Ochre - Hsv hsv2 = new Hsv(30, 0.833f, 0.8f); - Color color2 = hsv2; - - Assert.Equal(color2.R, 204); - Assert.Equal(color2.G, 119); - Assert.Equal(color2.B, 34); - - // White - Hsv hsv3 = new Hsv(0, 0, 1); - Color color3 = hsv3; - - Assert.Equal(color3.B, 255); - Assert.Equal(color3.G, 255); - Assert.Equal(color3.R, 255); - - // Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // Hsv hsv4 = color4; - // Assert.Equal(color4, (Color)hsv4); - //} - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void ColorToHsl() - { - // Black - Color b = Color.Black; - Hsl h = b; - - Assert.Equal(0, h.H, 1); - Assert.Equal(0, h.S, 1); - Assert.Equal(0, h.L, 1); - - // White - Color color = Color.White; - Hsl hsl = color; - - Assert.Equal(0f, hsl.H, 1); - Assert.Equal(0f, hsl.S, 1); - Assert.Equal(1f, hsl.L, 1); - - // Dark moderate pink. - Color color2 = new Color(128, 64, 106); - Hsl hsl2 = color2; - - Assert.Equal(320.6f, hsl2.H, 1); - Assert.Equal(0.33f, hsl2.S, 1); - Assert.Equal(0.376f, hsl2.L, 2); - - // Ochre. - Color color3 = new Color(204, 119, 34); - Hsl hsl3 = color3; - - Assert.Equal(30f, hsl3.H, 1); - Assert.Equal(0.714f, hsl3.S, 3); - Assert.Equal(0.467f, hsl3.L, 3); - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - public void HslToColor() - { - // Dark moderate pink. - Hsl hsl = new Hsl(320.6f, 0.33f, 0.376f); - Color color = hsl; - - Assert.Equal(color.R, 128); - Assert.Equal(color.G, 64); - Assert.Equal(color.B, 106); - - // Ochre - Hsl hsl2 = new Hsl(30, 0.714f, 0.467f); - Color color2 = hsl2; - - Assert.Equal(color2.R, 204); - Assert.Equal(color2.G, 119); - Assert.Equal(color2.B, 34); - - // White - Hsl hsl3 = new Hsl(0, 0, 1); - Color color3 = hsl3; - - Assert.Equal(color3.R, 255); - Assert.Equal(color3.G, 255); - Assert.Equal(color3.B, 255); - - // Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // Hsl hsl4 = color4; - // Assert.Equal(color4, (Color)hsl4); - //} - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", - Justification = "Reviewed. Suppression is OK here.")] - public void ColorToCmyk() - { - // White - Color color = Color.White; - Cmyk cmyk = color; - - Assert.Equal(0, cmyk.C, 1); - Assert.Equal(0, cmyk.M, 1); - Assert.Equal(0, cmyk.Y, 1); - Assert.Equal(0, cmyk.K, 1); - - // Black - Color color2 = Color.Black; - Cmyk cmyk2 = color2; - Assert.Equal(0, cmyk2.C, 1); - Assert.Equal(0, cmyk2.M, 1); - Assert.Equal(0, cmyk2.Y, 1); - Assert.Equal(1, cmyk2.K, 1); - - // Gray - Color color3 = Color.Gray; - Cmyk cmyk3 = color3; - Assert.Equal(0f, cmyk3.C, 1); - Assert.Equal(0f, cmyk3.M, 1); - Assert.Equal(0f, cmyk3.Y, 1); - Assert.Equal(0.498, cmyk3.K, 2); // Checked with other online converters. - - // Cyan - Color color4 = Color.Cyan; - Cmyk cmyk4 = color4; - Assert.Equal(1, cmyk4.C, 1); - Assert.Equal(0f, cmyk4.M, 1); - Assert.Equal(0f, cmyk4.Y, 1); - Assert.Equal(0f, cmyk4.K, 1); - } - - /// - /// Tests the implicit conversion from to . - /// - [Fact] - public void CmykToColor() - { - // Dark moderate pink. - Cmyk cmyk = new Cmyk(0f, .5f, .171f, .498f); - Color color = cmyk; - - Assert.Equal(color.R, 128); - Assert.Equal(color.G, 64); - Assert.Equal(color.B, 106); - - // Ochre - Cmyk cmyk2 = new Cmyk(0, .416f, .833f, .199f); - Color color2 = cmyk2; - - Assert.Equal(color2.R, 204); - Assert.Equal(color2.G, 119); - Assert.Equal(color2.B, 34); - - // White - Cmyk cmyk3 = new Cmyk(0, 0, 0, 0); - Color color3 = cmyk3; - - Assert.Equal(color3.R, 255); - Assert.Equal(color3.G, 255); - Assert.Equal(color3.B, 255); - - // Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // Cmyk cmyk4 = color4; - // Assert.Equal(color4, (Color)cmyk4); - //} - } - - /// - /// Tests the implicit conversion from to . - /// Comparison values obtained from - /// http://colormine.org/convert/rgb-to-lab - /// - [Fact] - public void ColorToCieLab() - { - // White - Color color = Color.White; - CieLab cielab = color; - - Assert.Equal(100, cielab.L, 3); - Assert.Equal(0.005, cielab.A, 3); - Assert.Equal(-0.010, cielab.B, 3); - - // Black - Color color2 = Color.Black; - CieLab cielab2 = color2; - Assert.Equal(0, cielab2.L, 3); - Assert.Equal(0, cielab2.A, 3); - Assert.Equal(0, cielab2.B, 3); - - // Gray - Color color3 = Color.Gray; - CieLab cielab3 = color3; - Assert.Equal(53.585, cielab3.L, 3); - Assert.Equal(0.003, cielab3.A, 3); - Assert.Equal(-0.006, cielab3.B, 3); - - // Cyan - Color color4 = Color.Cyan; - CieLab cielab4 = color4; - Assert.Equal(91.117, cielab4.L, 3); - Assert.Equal(-48.080, cielab4.A, 3); - Assert.Equal(-14.138, cielab4.B, 3); - } - - /// - /// Tests the implicit conversion from to . - /// - /// Comparison values obtained from - /// http://colormine.org/convert/rgb-to-lab - [Fact] - public void CieLabToColor() - { - // Dark moderate pink. - CieLab cielab = new CieLab(36.5492f, 33.3173f, -12.0615f); - Color color = cielab; - - Assert.Equal(color.R, 128); - Assert.Equal(color.G, 64); - Assert.Equal(color.B, 106); - - // Ochre - CieLab cielab2 = new CieLab(58.1758f, 27.3399f, 56.8240f); - Color color2 = cielab2; - - Assert.Equal(color2.R, 204); - Assert.Equal(color2.G, 119); - Assert.Equal(color2.B, 34); - - // Black - CieLab cielab3 = new CieLab(0, 0, 0); - Color color3 = cielab3; - - Assert.Equal(color3.R, 0); - Assert.Equal(color3.G, 0); - Assert.Equal(color3.B, 0); - - // Check others. - //Random random = new Random(0); - //for (int i = 0; i < 1000; i++) - //{ - // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); - // CieLab cielab4 = color4; - // Assert.Equal(color4, (Color)cielab4); - //} - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Colors/ColorDefinitionTests.cs b/tests/ImageSharp.Tests/Colors/ColorDefinitionTests.cs index 899ce4f77a..cb1161ebee 100644 --- a/tests/ImageSharp.Tests/Colors/ColorDefinitionTests.cs +++ b/tests/ImageSharp.Tests/Colors/ColorDefinitionTests.cs @@ -5,13 +5,10 @@ namespace ImageSharp.Tests { - using System; using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; - using ImageSharp.Colors.Spaces; using Xunit; public class ColorDefinitionTests { diff --git a/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs b/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs index b5b09c8288..8bda0bc8cc 100644 --- a/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs +++ b/tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs @@ -7,7 +7,6 @@ namespace ImageSharp.Tests.Colors { using System; using System.Numerics; - using ImageSharp.Colors.Spaces; using Xunit; /// @@ -38,38 +37,6 @@ namespace ImageSharp.Tests.Colors { new Short4(Vector4.One * 0x7FFF), new Short4(Vector4.One * 0x7FFF), typeof(Short4) }, }; - public static readonly TheoryData EqualityDataColorSpaces = - new TheoryData() - { - { new Bgra32(0, 0, 0), new Bgra32(0, 0, 0), typeof(Bgra32) }, - { new Bgra32(0, 0, 0, 0), new Bgra32(0, 0, 0, 0), typeof(Bgra32) }, - { new Bgra32(100, 100, 0, 0), new Bgra32(100, 100, 0, 0), typeof(Bgra32) }, - { new Bgra32(255, 255, 255), new Bgra32(255, 255, 255), typeof(Bgra32) }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, 0f, 0f), typeof(CieLab) }, - { new CieLab(1f, 1f, 1f), new CieLab(1f, 1f, 1f), typeof(CieLab) }, - { new CieLab(0f, -100f, -100f), new CieLab(0f, -100f, -100f), typeof(CieLab) }, - { new CieLab(0f, 100f, -100f), new CieLab(0f, 100f, -100f), typeof(CieLab) }, - { new CieLab(0f, -100f, 100f), new CieLab(0f, -100f, 100f), typeof(CieLab) }, - { new CieLab(0f, -100f, 50f), new CieLab(0f, -100f, 50f), typeof(CieLab) }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380f, 380f, 380f), typeof(CieXyz) }, - { new CieXyz(780f, 780f, 780f), new CieXyz(780f, 780f, 780f), typeof(CieXyz) }, - { new CieXyz(380f, 780f, 780f), new CieXyz(380f, 780f, 780f), typeof(CieXyz) }, - { new CieXyz(50f, 20f, 60f), new CieXyz(50f, 20f, 60f), typeof(CieXyz) }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 0f, 0f, 0f), typeof(Cmyk) }, - { new Cmyk(1f, 1f, 1f, 1f), new Cmyk(1f, 1f, 1f, 1f), typeof(Cmyk) }, - { new Cmyk(10f, 10f, 10f, 10f), new Cmyk(10f, 10f, 10f, 10f), typeof(Cmyk) }, - { new Cmyk(.4f, .5f, .1f, .2f), new Cmyk(.4f, .5f, .1f, .2f), typeof(Cmyk) }, - { new Hsl(0f, 0f, 0f), new Hsl(0f, 0f, 0f), typeof(Hsl) }, - { new Hsl(360f, 1f, 1f), new Hsl(360f, 1f, 1f), typeof(Hsl) }, - { new Hsl(100f, .5f, .1f), new Hsl(100f, .5f, .1f), typeof(Hsl) }, - { new Hsv(0f, 0f, 0f), new Hsv(0f, 0f, 0f), typeof(Hsv) }, - { new Hsv(360f, 1f, 1f), new Hsv(360f, 1f, 1f), typeof(Hsv) }, - { new Hsv(100f, .5f, .1f), new Hsv(100f, .5f, .1f), typeof(Hsv) }, - { new YCbCr(0, 0, 0), new YCbCr(0, 0, 0), typeof(YCbCr) }, - { new YCbCr(255, 255, 255), new YCbCr(255, 255, 255), typeof(YCbCr) }, - { new YCbCr(100, 100, 0), new YCbCr(100, 100, 0), typeof(YCbCr) }, - }; - public static readonly TheoryData NotEqualityDataNulls = new TheoryData() { @@ -94,18 +61,6 @@ namespace ImageSharp.Tests.Colors { new Short4(Vector4.One * 0x7FFF), null, typeof(Short4) }, }; - public static readonly TheoryData NotEqualityDataNullsColorSpaces = - new TheoryData() - { - { new Bgra32(0, 0, 0), null, typeof(Bgra32) }, - { new CieLab(0f, 0f, 0f), null, typeof(CieLab) }, - { new CieXyz(380f, 380f, 380f), null, typeof(CieXyz) }, - { new Cmyk(0f, 0f, 0f, 0f), null, typeof(Cmyk) }, - { new Hsl(0f, 0f, 0f), null, typeof(Hsl) }, - { new Hsv(360f, 1f, 1f), null, typeof(Hsv) }, - { new YCbCr(0, 0, 0), null, typeof(YCbCr) }, - }; - public static readonly TheoryData NotEqualityDataDifferentObjects = new TheoryData() { @@ -115,16 +70,6 @@ namespace ImageSharp.Tests.Colors { new Rgba1010102(Vector4.One), new Bgra5551(Vector4.Zero), null }, }; - public static readonly TheoryData NotEqualityDataDifferentObjectsColorSpaces = - new TheoryData() - { - // Valid objects of different types but not equal - { new Bgra32(0, 0, 0), new CieLab(0f, 0f, 0f), null }, - { new CieXyz(380f, 380f, 380f), new Cmyk(0f, 0f, 0f, 0f), null }, - { new Hsl(0f, 0f, 0f), new Hsv(360f, 1f, 1f), null }, - { new YCbCr(0, 0, 0), new Hsv(360f, 1f, 1f), null }, - }; - public static readonly TheoryData NotEqualityData = new TheoryData() { @@ -149,92 +94,8 @@ namespace ImageSharp.Tests.Colors { new Short4(Vector4.One * 0x7FFF), new Short4(Vector4.Zero), typeof(Short4) }, }; - public static readonly TheoryData NotEqualityDataColorSpaces = - new TheoryData() - { - { new Bgra32(0, 0, 0), new Bgra32(0, 1, 0), typeof(Bgra32) }, - { new Bgra32(0, 0, 0, 0), new Bgra32(0, 1, 0, 0), typeof(Bgra32) }, - { new Bgra32(100, 100, 0, 0), new Bgra32(100, 0, 0, 0), typeof(Bgra32) }, - { new Bgra32(255, 255, 255), new Bgra32(255, 0, 255), typeof(Bgra32) }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, 1f, 0f), typeof(CieLab) }, - { new CieLab(1f, 1f, 1f), new CieLab(1f, 0f, 1f), typeof(CieLab) }, - { new CieLab(0f, -100f, -100f), new CieLab(0f, 100f, -100f), typeof(CieLab) }, - { new CieLab(0f, 100f, -100f), new CieLab(0f, -100f, -100f), typeof(CieLab) }, - { new CieLab(0f, -100f, 100f), new CieLab(0f, 100f, 100f), typeof(CieLab) }, - { new CieLab(0f, -100f, 50f), new CieLab(0f, 100f, 20f), typeof(CieLab) }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380f, 0f, 380f), typeof(CieXyz) }, - { new CieXyz(780f, 780f, 780f), new CieXyz(780f, 0f, 780f), typeof(CieXyz) }, - { new CieXyz(380f, 780f, 780f), new CieXyz(380f, 0f, 780f), typeof(CieXyz) }, - { new CieXyz(50f, 20f, 60f), new CieXyz(50f, 0f, 60f), typeof(CieXyz) }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 1f, 0f, 0f), typeof(Cmyk) }, - { new Cmyk(1f, 1f, 1f, 1f), new Cmyk(1f, 1f, 0f, 1f), typeof(Cmyk) }, - { new Cmyk(10f, 10f, 10f, 10f), new Cmyk(10f, 10f, 0f, 10f), typeof(Cmyk) }, - { new Cmyk(.4f, .5f, .1f, .2f), new Cmyk(.4f, .5f, 5f, .2f), typeof(Cmyk) }, - { new Hsl(0f, 0f, 0f), new Hsl(0f, 5f, 0f), typeof(Hsl) }, - { new Hsl(360f, 1f, 1f), new Hsl(360f, .5f, 1f), typeof(Hsl) }, - { new Hsl(100f, .5f, .1f), new Hsl(100f, 9f, .1f), typeof(Hsl) }, - { new Hsv(0f, 0f, 0f), new Hsv(0f, 1f, 0f), typeof(Hsv) }, - { new Hsv(360f, 1f, 1f), new Hsv(0f, 1f, 1f), typeof(Hsv) }, - { new Hsv(100f, .5f, .1f), new Hsv(2f, .5f, .1f), typeof(Hsv) }, - { new YCbCr(0, 0, 0), new YCbCr(0, 1, 0), typeof(YCbCr) }, - { new YCbCr(255, 255, 255), new YCbCr(255, 0, 255), typeof(YCbCr) }, - { new YCbCr(100, 100, 0), new YCbCr(100, 20, 0), typeof(YCbCr) }, - }; - - public static readonly TheoryData AlmostEqualsData = - new TheoryData() - { - { new CieLab(0f, 0f, 0f), new CieLab(0f, 0f, 0f), typeof(CieLab), 0f }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, 0f, 0f), typeof(CieLab), .001f }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, 0f, 0f), typeof(CieLab), .0001f }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, 0f, 0f), typeof(CieLab), .0005f }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, .001f, 0f), typeof(CieLab), .001f }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, 0f, .0001f), typeof(CieLab), .0001f }, - { new CieLab(0f, 0f, 0f), new CieLab(.0005f, 0f, 0f), typeof(CieLab), .0005f }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380f, 380f, 380f), typeof(CieXyz), 0f }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380.001f, 380f, 380f), typeof(CieXyz), .01f }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380f, 380.001f, 380f), typeof(CieXyz), .01f }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380f, 380f, 380.001f), typeof(CieXyz), .01f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 0f, 0f, 0f), typeof(Cmyk), 0f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0.001f, 0f, 0f, 0f), typeof(Cmyk), .01f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 0.001f, 0f, 0f), typeof(Cmyk), .01f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 0f, 0.001f, 0f), typeof(Cmyk), .01f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 0f, 0f, 0.001f), typeof(Cmyk), .01f }, - { new Hsl(0f, 0f, 0f), new Hsl(0f, 0f, 0f), typeof(Hsl), 0f }, - { new Hsl(0f, 0f, 0f), new Hsl(0.001f, 0f, 0f), typeof(Hsl), .01f }, - { new Hsl(0f, 0f, 0f), new Hsl(0f, 0.001f, 0f), typeof(Hsl), .01f }, - { new Hsl(0f, 0f, 0f), new Hsl(0f, 0f, 0.001f), typeof(Hsl), .01f }, - { new Hsv(360f, 1f, 1f), new Hsv(360f, 1f, 1f), typeof(Hsv), 0f }, - { new Hsv(0f, 0f, 0f), new Hsv(0f, 0f, 0f), typeof(Hsv), 0f }, - { new Hsv(0f, 0f, 0f), new Hsv(0.001f, 0f, 0f), typeof(Hsv), .01f }, - { new Hsv(0f, 0f, 0f), new Hsv(0f, 0.001f, 0f), typeof(Hsv), .01f }, - { new Hsv(0f, 0f, 0f), new Hsv(0f, 0f, 0.001f), typeof(Hsv), .01f }, - }; - - public static readonly TheoryData AlmostNotEqualsData = - new TheoryData() - { - { new CieLab(0f, 0f, 0f), new CieLab(0.1f, 0f, 0f), typeof(CieLab), .001f }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, 0.1f, 0f), typeof(CieLab), .001f }, - { new CieLab(0f, 0f, 0f), new CieLab(0f, 0f, 0.1f), typeof(CieLab), .001f }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380.1f, 380f, 380f), typeof(CieXyz), .001f }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380f, 380.1f, 380f), typeof(CieXyz), .001f }, - { new CieXyz(380f, 380f, 380f), new CieXyz(380f, 380f, 380.1f), typeof(CieXyz), .001f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0.1f, 0f, 0f, 0f), typeof(Cmyk), .001f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 0.1f, 0f, 0f), typeof(Cmyk), .001f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 0f, 0.1f, 0f), typeof(Cmyk), .001f }, - { new Cmyk(0f, 0f, 0f, 0f), new Cmyk(0f, 0f, 0f, 0.1f), typeof(Cmyk), .001f }, - { new Hsl(0f, 0f, 0f), new Hsl(0.1f, 0f, 0f), typeof(Hsl), .001f }, - { new Hsl(0f, 0f, 0f), new Hsl(0f, 0.1f, 0f), typeof(Hsl), .001f }, - { new Hsl(0f, 0f, 0f), new Hsl(0f, 0f, 0.1f), typeof(Hsl), .001f }, - { new Hsv(0f, 0f, 0f), new Hsv(0.1f, 0f, 0f), typeof(Hsv), .001f }, - { new Hsv(0f, 0f, 0f), new Hsv(0f, 0.1f, 0f), typeof(Hsv), .001f }, - { new Hsv(0f, 0f, 0f), new Hsv(0f, 0f, 0.1f), typeof(Hsv), .001f }, - }; - [Theory] [MemberData(nameof(EqualityData))] - [MemberData(nameof(EqualityDataColorSpaces))] public void Equality(object first, object second, Type type) { // Act @@ -246,11 +107,8 @@ namespace ImageSharp.Tests.Colors [Theory] [MemberData(nameof(NotEqualityDataNulls))] - [MemberData(nameof(NotEqualityDataNullsColorSpaces))] [MemberData(nameof(NotEqualityDataDifferentObjects))] - [MemberData(nameof(NotEqualityDataDifferentObjectsColorSpaces))] [MemberData(nameof(NotEqualityData))] - [MemberData(nameof(NotEqualityDataColorSpaces))] public void NotEquality(object first, object second, Type type) { // Act @@ -262,7 +120,6 @@ namespace ImageSharp.Tests.Colors [Theory] [MemberData(nameof(EqualityData))] - [MemberData(nameof(EqualityDataColorSpaces))] public void HashCodeEqual(object first, object second, Type type) { // Act @@ -274,7 +131,6 @@ namespace ImageSharp.Tests.Colors [Theory] [MemberData(nameof(NotEqualityDataDifferentObjects))] - [MemberData(nameof(NotEqualityDataDifferentObjectsColorSpaces))] public void HashCodeNotEqual(object first, object second, Type type) { // Act @@ -286,13 +142,12 @@ namespace ImageSharp.Tests.Colors [Theory] [MemberData(nameof(EqualityData))] - [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); @@ -305,13 +160,12 @@ namespace ImageSharp.Tests.Colors [Theory] [MemberData(nameof(NotEqualityData))] - [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); @@ -324,13 +178,12 @@ namespace ImageSharp.Tests.Colors [Theory] [MemberData(nameof(EqualityData))] - [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); @@ -343,13 +196,12 @@ namespace ImageSharp.Tests.Colors [Theory] [MemberData(nameof(NotEqualityData))] - [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); @@ -359,41 +211,5 @@ namespace ImageSharp.Tests.Colors // Assert Assert.True(notEqual); } - - [Theory] - [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 :) - dynamic firstObject = Convert.ChangeType(first, type); - dynamic secondObject = Convert.ChangeType(second, type); - - // Act - dynamic almostEqual = firstObject.AlmostEquals(secondObject, precision); - - // Assert - Assert.True(almostEqual); - } - - [Theory] - [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 :) - dynamic firstObject = Convert.ChangeType(first, type); - dynamic secondObject = Convert.ChangeType(second, type); - - // Act - dynamic almostEqual = firstObject.AlmostEquals(secondObject, precision); - - // Assert - Assert.False(almostEqual); - } } }