Browse Source

Add luminance color profile type and cleanup

pull/1567/head
James Jackson-South 1 year ago
parent
commit
1d27038551
  1. 2
      src/ImageSharp/ColorProfiles/CieLab.cs
  2. 14
      src/ImageSharp/ColorProfiles/CieLch.cs
  3. 14
      src/ImageSharp/ColorProfiles/CieLchuv.cs
  4. 1
      src/ImageSharp/ColorProfiles/CieLuv.cs
  5. 2
      src/ImageSharp/ColorProfiles/CieXyy.cs
  6. 1
      src/ImageSharp/ColorProfiles/CieXyz.cs
  7. 15
      src/ImageSharp/ColorProfiles/Cmyk.cs
  8. 5
      src/ImageSharp/ColorProfiles/ColorConversionOptions.cs
  9. 13
      src/ImageSharp/ColorProfiles/Hsl.cs
  10. 13
      src/ImageSharp/ColorProfiles/Hsv.cs
  11. 1
      src/ImageSharp/ColorProfiles/HunterLab.cs
  12. 2
      src/ImageSharp/ColorProfiles/IColorProfile.cs
  13. 27
      src/ImageSharp/ColorProfiles/KnownYCoefficients.cs
  14. 1
      src/ImageSharp/ColorProfiles/Lms.cs
  15. 1
      src/ImageSharp/ColorProfiles/Rgb.cs
  16. 136
      src/ImageSharp/ColorProfiles/Y.cs
  17. 16
      src/ImageSharp/ColorProfiles/YCbCr.cs
  18. 7
      tests/ImageSharp.Tests/ColorProfiles/ApproximateColorProfileComparer.cs
  19. 113
      tests/ImageSharp.Tests/ColorProfiles/RbgAndYConversionTests.cs
  20. 42
      tests/ImageSharp.Tests/ColorProfiles/YTests.cs

2
src/ImageSharp/ColorProfiles/CieLab.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;
@ -36,7 +35,6 @@ public readonly struct CieLab : IProfileConnectingSpace<CieLab, CieXyz>
/// <param name="vector">The vector representing the l, a, b components.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieLab(Vector3 vector)
: this()
{
this.L = vector.X;
this.A = vector.Y;

14
src/ImageSharp/ColorProfiles/CieLch.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;
@ -43,6 +42,17 @@ public readonly struct CieLch : IColorProfile<CieLch, CieLab>
this.H = vector.Z;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
private CieLch(Vector3 vector, bool _)
#pragma warning restore SA1313 // Parameter names should begin with lower-case letter
{
vector = Vector3.Clamp(vector, Min, Max);
this.L = vector.X;
this.C = vector.Y;
this.H = vector.Z;
}
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
@ -99,7 +109,7 @@ public readonly struct CieLch : IColorProfile<CieLch, CieLab>
Vector3 v3 = source.AsVector3();
v3 *= new Vector3(100, 400, 360);
v3 -= new Vector3(0, 200, 0);
return new CieLch(v3);
return new CieLch(v3, true);
}
/// <inheritdoc/>

14
src/ImageSharp/ColorProfiles/CieLchuv.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;
@ -36,7 +35,6 @@ public readonly struct CieLchuv : IColorProfile<CieLchuv, CieXyz>
/// <param name="vector">The vector representing the l, c, h components.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieLchuv(Vector3 vector)
: this()
{
vector = Vector3.Clamp(vector, Min, Max);
this.L = vector.X;
@ -44,6 +42,16 @@ public readonly struct CieLchuv : IColorProfile<CieLchuv, CieXyz>
this.H = vector.Z;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
private CieLchuv(Vector3 vector, bool _)
#pragma warning restore SA1313 // Parameter names should begin with lower-case letter
{
this.L = vector.X;
this.C = vector.Y;
this.H = vector.Z;
}
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
@ -98,7 +106,7 @@ public readonly struct CieLchuv : IColorProfile<CieLchuv, CieXyz>
Vector3 v3 = source.AsVector3();
v3 *= new Vector3(100, 400, 360);
v3 -= new Vector3(0, 200, 0);
return new CieLchuv(v3);
return new CieLchuv(v3, true);
}
/// <inheritdoc/>

1
src/ImageSharp/ColorProfiles/CieLuv.cs

@ -37,7 +37,6 @@ public readonly struct CieLuv : IColorProfile<CieLuv, CieXyz>
/// <param name="vector">The vector representing the l, u, v components.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieLuv(Vector3 vector)
: this()
{
this.L = vector.X;
this.U = vector.Y;

2
src/ImageSharp/ColorProfiles/CieXyy.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;
@ -36,7 +35,6 @@ public readonly struct CieXyy : IColorProfile<CieXyy, CieXyz>
/// <param name="vector">The vector representing the x, y, Y components.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieXyy(Vector3 vector)
: this()
{
// Not clamping as documentation about this space only indicates "usual" ranges
this.X = vector.X;

1
src/ImageSharp/ColorProfiles/CieXyz.cs

@ -34,7 +34,6 @@ public readonly struct CieXyz : IProfileConnectingSpace<CieXyz, CieXyz>
/// </summary>
/// <param name="vector">The vector representing the x, y, z components.</param>
public CieXyz(Vector3 vector)
: this()
{
this.X = vector.X;
this.Y = vector.Y;

15
src/ImageSharp/ColorProfiles/Cmyk.cs

@ -36,7 +36,18 @@ public readonly struct Cmyk : IColorProfile<Cmyk, Rgb>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Cmyk(Vector4 vector)
{
vector = Numerics.Clamp(vector, Min, Max);
vector = Vector4.Clamp(vector, Min, Max);
this.C = vector.X;
this.M = vector.Y;
this.Y = vector.Z;
this.K = vector.W;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
private Cmyk(Vector4 vector, bool _)
#pragma warning restore SA1313 // Parameter names should begin with lower-case letter
{
this.C = vector.X;
this.M = vector.Y;
this.Y = vector.Z;
@ -99,7 +110,7 @@ public readonly struct Cmyk : IColorProfile<Cmyk, Rgb>
/// <inheritdoc/>
public static Cmyk FromScaledVector4(Vector4 source)
=> new(source);
=> new(source, true);
/// <inheritdoc/>
public static void ToScaledVector4(ReadOnlySpan<Cmyk> source, Span<Vector4> destination)

5
src/ImageSharp/ColorProfiles/ColorConversionOptions.cs

@ -45,6 +45,11 @@ public class ColorConversionOptions
/// </summary>
public RgbWorkingSpace TargetRgbWorkingSpace { get; init; } = KnownRgbWorkingSpaces.SRgb;
/// <summary>
/// Gets the Y (luma) coefficients to use in conversions from RGB.
/// </summary>
public Vector3 YCoefficients { get; init; } = KnownYCoefficients.BT709;
/// <summary>
/// Gets the source ICC profile.
/// </summary>

13
src/ImageSharp/ColorProfiles/Hsl.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;
@ -42,6 +41,16 @@ public readonly struct Hsl : IColorProfile<Hsl, Rgb>
this.L = vector.Z;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
private Hsl(Vector3 vector, bool _)
#pragma warning restore SA1313 // Parameter names should begin with lower-case letter
{
this.H = vector.X;
this.S = vector.Y;
this.L = vector.Z;
}
/// <summary>
/// Gets the hue component.
/// <remarks>A value ranging between 0 and 360.</remarks>
@ -90,7 +99,7 @@ public readonly struct Hsl : IColorProfile<Hsl, Rgb>
/// <inheritdoc/>
public static Hsl FromScaledVector4(Vector4 source)
=> new(source.AsVector3() * 360F);
=> new(source.AsVector3() * 360F, true);
/// <inheritdoc/>
public static void ToScaledVector4(ReadOnlySpan<Hsl> source, Span<Vector4> destination)

13
src/ImageSharp/ColorProfiles/Hsv.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;
@ -42,6 +41,16 @@ public readonly struct Hsv : IColorProfile<Hsv, Rgb>
this.V = vector.Z;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
private Hsv(Vector3 vector, bool _)
#pragma warning restore SA1313 // Parameter names should begin with lower-case letter
{
this.H = vector.X;
this.S = vector.Y;
this.V = vector.Z;
}
/// <summary>
/// Gets the hue component.
/// <remarks>A value ranging between 0 and 360.</remarks>
@ -88,7 +97,7 @@ public readonly struct Hsv : IColorProfile<Hsv, Rgb>
/// <inheritdoc/>
public static Hsv FromScaledVector4(Vector4 source)
=> new(source.AsVector3() * 360F);
=> new(source.AsVector3() * 360F, true);
/// <inheritdoc/>
public static void ToScaledVector4(ReadOnlySpan<Hsv> source, Span<Vector4> destination)

1
src/ImageSharp/ColorProfiles/HunterLab.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;

2
src/ImageSharp/ColorProfiles/IColorProfile.cs

@ -30,7 +30,7 @@ public interface IColorProfile<TSelf> : IColorProfile, IEquatable<TSelf>
/// The vector components are typically expanded in least to greatest significance order.
/// </summary>
/// <returns>The <see cref="Vector4"/>.</returns>
Vector4 ToScaledVector4();
public Vector4 ToScaledVector4();
#pragma warning disable CA1000 // Do not declare static members on generic types
/// <summary>

27
src/ImageSharp/ColorProfiles/KnownYCoefficients.cs

@ -0,0 +1,27 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Numerics;
namespace SixLabors.ImageSharp.ColorProfiles;
/// <summary>
/// Provides standard Y (luma) coefficient sets for weighted RGB conversions.
/// </summary>
public static class KnownYCoefficients
{
/// <summary>
/// ITU-R BT.601 (SD video standard).
/// </summary>
public static readonly Vector3 BT601 = new(0.299F, 0.587F, 0.114F);
/// <summary>
/// ITU-R BT.709 (HD video, sRGB standard).
/// </summary>
public static readonly Vector3 BT709 = new(0.2126F, 0.7152F, 0.0722F);
/// <summary>
/// ITU-R BT.2020 (UHD/4K video standard).
/// </summary>
public static readonly Vector3 BT2020 = new(0.2627F, 0.6780F, 0.0593F);
}

1
src/ImageSharp/ColorProfiles/Lms.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;

1
src/ImageSharp/ColorProfiles/Rgb.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using SixLabors.ImageSharp.ColorProfiles.WorkingSpaces;
namespace SixLabors.ImageSharp.ColorProfiles;

136
src/ImageSharp/ColorProfiles/Y.cs

@ -0,0 +1,136 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.ColorProfiles;
/// <summary>
/// Represents a Y (luminance) color.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public readonly struct Y : IColorProfile<Y, Rgb>
{
/// <summary>
/// Initializes a new instance of the <see cref="Y"/> struct.
/// </summary>
/// <param name="l">The luminance component.</param>
public Y(float l) => this.L = l;
/// <summary>
/// Gets the luminance component.
/// </summary>
/// <remarks>A value ranging between 0 and 1.</remarks>
public float L { get; }
/// <summary>
/// Compares two <see cref="Y"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Y"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Y"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Y left, Y right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Y"/> objects for inequality.
/// </summary>
/// <param name="left">The <see cref="Y"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Y"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Y left, Y right) => !left.Equals(right);
/// <inheritdoc/>
public static Y FromProfileConnectingSpace(ColorConversionOptions options, in Rgb source)
{
Vector3 weights = options.YCoefficients;
float l = (weights.X * source.R) + (weights.Y * source.G) + (weights.Z * source.B);
return new Y(l);
}
/// <inheritdoc/>
public static void FromProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Rgb> source, Span<Y> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
// TODO: We can optimize this by using SIMD
for (int i = 0; i < source.Length; i++)
{
Rgb rgb = source[i];
destination[i] = FromProfileConnectingSpace(options, in rgb);
}
}
/// <inheritdoc/>
public Vector4 ToScaledVector4() => new(this.L);
/// <inheritdoc/>
public static Y FromScaledVector4(Vector4 source) => new(source.X);
/// <inheritdoc/>
public static void ToScaledVector4(ReadOnlySpan<Y> source, Span<Vector4> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
// TODO: Optimize via SIMD
for (int i = 0; i < source.Length; i++)
{
destination[i] = source[i].ToScaledVector4();
}
}
/// <inheritdoc/>
public static void FromScaledVector4(ReadOnlySpan<Vector4> source, Span<Y> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
// TODO: Optimize via SIMD
for (int i = 0; i < source.Length; i++)
{
destination[i] = FromScaledVector4(source[i]);
}
}
/// <inheritdoc/>
public Rgb ToProfileConnectingSpace(ColorConversionOptions options)
=> new(this.L, this.L, this.L);
/// <inheritdoc/>
public static void ToProfileConnectionSpace(ColorConversionOptions options, ReadOnlySpan<Y> source, Span<Rgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
// TODO: We can optimize this by using SIMD
for (int i = 0; i < source.Length; i++)
{
destination[i] = source[i].ToProfileConnectingSpace(options);
}
}
/// <inheritdoc/>
public static ChromaticAdaptionWhitePointSource GetChromaticAdaptionWhitePointSource()
=> ChromaticAdaptionWhitePointSource.RgbWorkingSpace;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
=> this.L.GetHashCode();
/// <inheritdoc/>
public override string ToString()
=> FormattableString.Invariant($"Y({this.L:#0.##})");
/// <inheritdoc/>
public override bool Equals(object? obj)
=> obj is Y other && this.Equals(other);
/// <inheritdoc/>
public bool Equals(Y other) => this.L == other.L;
}

16
src/ImageSharp/ColorProfiles/YCbCr.cs

@ -4,7 +4,6 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace SixLabors.ImageSharp.ColorProfiles;
@ -44,6 +43,16 @@ public readonly struct YCbCr : IColorProfile<YCbCr, Rgb>
this.Cr = vector.Z;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
private YCbCr(Vector3 vector, bool _)
#pragma warning restore SA1313 // Parameter names should begin with lower-case letter
{
this.Y = vector.X;
this.Cb = vector.Y;
this.Cr = vector.Z;
}
/// <summary>
/// Gets the Y luminance component.
/// <remarks>A value ranging between 0 and 255.</remarks>
@ -97,7 +106,7 @@ public readonly struct YCbCr : IColorProfile<YCbCr, Rgb>
{
Vector3 v3 = source.AsVector3();
v3 *= Max;
return new YCbCr(v3);
return new YCbCr(v3, true);
}
/// <inheritdoc/>
@ -174,8 +183,7 @@ public readonly struct YCbCr : IColorProfile<YCbCr, Rgb>
// TODO: We can optimize this by using SIMD
for (int i = 0; i < source.Length; i++)
{
YCbCr ycbcr = source[i];
destination[i] = ycbcr.ToProfileConnectingSpace(options);
destination[i] = source[i].ToProfileConnectingSpace(options);
}
}

7
tests/ImageSharp.Tests/ColorProfiles/ApproximateColorProfileComparer.cs

@ -22,7 +22,8 @@ internal readonly struct ApproximateColorProfileComparer :
IEqualityComparer<Cmyk>,
IEqualityComparer<Hsl>,
IEqualityComparer<Hsv>,
IEqualityComparer<HunterLab>
IEqualityComparer<HunterLab>,
IEqualityComparer<Y>
{
private readonly float epsilon;
@ -58,6 +59,8 @@ internal readonly struct ApproximateColorProfileComparer :
public bool Equals(HunterLab x, HunterLab y) => this.Equals(x.L, y.L) && this.Equals(x.A, y.A) && this.Equals(x.B, y.B);
public bool Equals(Y x, Y y) => this.Equals(x.L, y.L);
public int GetHashCode([DisallowNull] CieLab obj) => obj.GetHashCode();
public int GetHashCode([DisallowNull] CieXyz obj) => obj.GetHashCode();
@ -84,6 +87,8 @@ internal readonly struct ApproximateColorProfileComparer :
public int GetHashCode([DisallowNull] HunterLab obj) => obj.GetHashCode();
public int GetHashCode([DisallowNull] Y obj) => obj.GetHashCode();
private bool Equals(float x, float y)
{
float d = x - y;

113
tests/ImageSharp.Tests/ColorProfiles/RbgAndYConversionTests.cs

@ -0,0 +1,113 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.ColorProfiles;
namespace SixLabors.ImageSharp.Tests.ColorProfiles;
/// <summary>
/// Tests <see cref="Rgb"/>-<see cref="Y"/> conversions.
/// </summary>
/// <remarks>
/// Test data generated mathematically
/// </remarks>
public class RbgAndYConversionTests
{
private static readonly ApproximateColorProfileComparer Comparer = new(.001F);
[Theory]
[InlineData(0F, 0F, 0F, 0F)]
[InlineData(0.5F, 0.5F, 0.5F, 0.5F)]
[InlineData(1F, 1F, 1F, 1F)]
public void Convert_Y_To_Rgb(float y, float r, float g, float b)
{
// Arrange
Y input = new(y);
Rgb expected = new(r, g, b);
ColorProfileConverter converter = new();
Span<Y> inputSpan = new Y[5];
inputSpan.Fill(input);
Span<Rgb> actualSpan = new Rgb[5];
// Act
Rgb actual = converter.Convert<Y, Rgb>(input);
converter.Convert<Y, Rgb>(inputSpan, actualSpan);
// Assert
Assert.Equal(expected, actual, Comparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], Comparer);
}
}
[Theory]
[InlineData(0F, 0F, 0F, 0F)]
[InlineData(0.5F, 0.5F, 0.5F, 0.5F)]
[InlineData(1F, 1F, 1F, 1F)]
public void Convert_Rgb_To_Y_BT601(float r, float g, float b, float y)
{
ColorConversionOptions options = new()
{
YCoefficients = KnownYCoefficients.BT601
};
Convert_Rgb_To_Y_Core(r, g, b, y, options);
}
[Theory]
[InlineData(0F, 0F, 0F, 0F)]
[InlineData(0.5F, 0.5F, 0.5F, 0.5F)]
[InlineData(1F, 1F, 1F, 1F)]
public void Convert_Rgb_To_Y_BT709(float r, float g, float b, float y)
{
ColorConversionOptions options = new()
{
YCoefficients = KnownYCoefficients.BT709
};
Convert_Rgb_To_Y_Core(r, g, b, y, options);
}
[Theory]
[InlineData(0F, 0F, 0F, 0F)]
[InlineData(0.5F, 0.5F, 0.5F, 0.49999997F)]
[InlineData(1F, 1F, 1F, 0.99999994F)]
public void Convert_Rgb_To_Y_BT2020(float r, float g, float b, float y)
{
ColorConversionOptions options = new()
{
YCoefficients = KnownYCoefficients.BT2020
};
Convert_Rgb_To_Y_Core(r, g, b, y, options);
}
private static void Convert_Rgb_To_Y_Core(float r, float g, float b, float y, ColorConversionOptions options)
{
// Arrange
Rgb input = new(r, g, b);
Y expected = new(y);
ColorProfileConverter converter = new(options);
Span<Rgb> inputSpan = new Rgb[5];
inputSpan.Fill(input);
Span<Y> actualSpan = new Y[5];
// Act
Y actual = converter.Convert<Rgb, Y>(input);
converter.Convert<Rgb, Y>(inputSpan, actualSpan);
// Assert
Assert.Equal(expected, actual, Comparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], Comparer);
}
}
}

42
tests/ImageSharp.Tests/ColorProfiles/YTests.cs

@ -0,0 +1,42 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.ColorProfiles;
namespace SixLabors.ImageSharp.Tests.ColorProfiles;
/// <summary>
/// Tests the <see cref="Y"/> struct.
/// </summary>
[Trait("Color", "Conversion")]
public class YTests
{
[Fact]
public void YConstructorAssignsFields()
{
const float y = .75F;
Y yValue = new(y);
Assert.Equal(y, yValue.L);
}
[Fact]
public void YEquality()
{
Y x = default;
Y y = new(1F);
Assert.True(default == default(Y));
Assert.False(default != default(Y));
Assert.Equal(default, default(Y));
Assert.Equal(new Y(1), new Y(1));
Assert.Equal(new Y(.5F), new Y(.5F));
Assert.False(x.Equals(y));
Assert.False(x.Equals((object)y));
Assert.False(x.GetHashCode().Equals(y.GetHashCode()));
}
}
Loading…
Cancel
Save