Browse Source

Bulk colorspace conversion tests

af/merge-core
James Jackson-South 8 years ago
parent
commit
53798df51c
  1. 33
      src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs
  2. 112
      tests/ImageSharp.Tests/Colorspaces/ApproximateColorspaceComparer.cs
  3. 23
      tests/ImageSharp.Tests/Colorspaces/CieLabAndCieLchConversionTests.cs
  4. 24
      tests/ImageSharp.Tests/Colorspaces/CieLuvAndCieLchuvConversionTests.cs
  5. 23
      tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieLabConversionTest.cs
  6. 23
      tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieLuvConversionTest.cs
  7. 24
      tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieXyyConversionTest.cs
  8. 34
      tests/ImageSharp.Tests/Colorspaces/CieXyzAndHunterLabConversionTest.cs
  9. 13
      tests/ImageSharp.Tests/Colorspaces/CieXyzAndLmsConversionTest.cs
  10. 5
      tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs
  11. 87
      tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs
  12. 46
      tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs
  13. 46
      tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs
  14. 45
      tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs
  15. 45
      tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs
  16. 76
      tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs
  17. 68
      tests/ImageSharp.Tests/TestUtilities/FloatRoundingComparer.cs

33
src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs

@ -1,12 +1,14 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Trivial implementation of <see cref="RgbWorkingSpace"/>
/// </summary>
internal class RgbWorkingSpace
internal class RgbWorkingSpace : IEquatable<RgbWorkingSpace>
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbWorkingSpace"/> class.
@ -39,12 +41,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// <summary>
/// Compares two <see cref="RgbWorkingSpace"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="RgbWorkingSpace"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="RgbWorkingSpace"/> on the right side of the operand.
/// </param>
/// <param name="left">The <see cref="RgbWorkingSpace"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="RgbWorkingSpace"/> 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>
@ -56,12 +54,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// <summary>
/// Compares two <see cref="RgbWorkingSpace"/> objects for inequality
/// </summary>
/// <param name="left">
/// The <see cref="RgbWorkingSpace"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="RgbWorkingSpace"/> on the right side of the operand.
/// </param>
/// <param name="left">The <see cref="RgbWorkingSpace"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="RgbWorkingSpace"/> 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>
@ -70,11 +64,13 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return !Equals(left, right);
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is RgbWorkingSpace other && this.Equals(other);
}
/// <inheritdoc/>
public bool Equals(RgbWorkingSpace other)
{
// TODO: Object.Equals for ICompanding will be slow.
@ -86,13 +82,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
int hashCode = this.WhitePoint.GetHashCode();
hashCode = (hashCode * 397) ^ this.ChromaticityCoordinates.GetHashCode();
hashCode = (hashCode * 397) ^ (this.Companding?.GetHashCode() ?? 0);
return hashCode;
}
int hash = this.WhitePoint.GetHashCode();
hash = HashHelpers.Combine(hash, this.ChromaticityCoordinates.GetHashCode());
hash = HashHelpers.Combine(hash, this.Companding?.GetHashCode() ?? 0);
return hash;
}
}
}

112
tests/ImageSharp.Tests/Colorspaces/ApproximateColorspaceComparer.cs

@ -3,13 +3,14 @@
using System.Collections.Generic;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.Tests.Colorspaces
{
/// <summary>
/// Allows the approximate comparison of colorspace component values.
/// </summary>
internal class ApproximateColorSpaceComparer :
internal readonly struct ApproximateColorSpaceComparer :
IEqualityComparer<Rgb>,
IEqualityComparer<CieLab>,
IEqualityComparer<CieLch>,
@ -17,8 +18,15 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
IEqualityComparer<CieLuv>,
IEqualityComparer<CieXyz>,
IEqualityComparer<CieXyy>,
IEqualityComparer<Cmyk>,
IEqualityComparer<HunterLab>,
IEqualityComparer<Lms>
IEqualityComparer<Hsl>,
IEqualityComparer<Hsv>,
IEqualityComparer<Lms>,
IEqualityComparer<YCbCr>,
IEqualityComparer<CieXyChromaticityCoordinates>,
IEqualityComparer<RgbPrimariesChromaticityCoordinates>,
IEqualityComparer<RgbWorkingSpace>
{
private readonly float Epsilon;
@ -129,6 +137,21 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(Cmyk x, Cmyk y)
{
return this.Equals(x.C, y.C)
&& this.Equals(x.M, y.M)
&& this.Equals(x.Y, y.Y)
&& this.Equals(x.K, y.K);
}
/// <inheritdoc/>
public int GetHashCode(Cmyk obj)
{
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(HunterLab x, HunterLab y)
{
@ -143,6 +166,34 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(Hsl x, Hsl y)
{
return this.Equals(x.H, y.H)
&& this.Equals(x.S, y.S)
&& this.Equals(x.L, y.L);
}
/// <inheritdoc/>
public int GetHashCode(Hsl obj)
{
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(Hsv x, Hsv y)
{
return this.Equals(x.H, y.H)
&& this.Equals(x.S, y.S)
&& this.Equals(x.V, y.V);
}
/// <inheritdoc/>
public int GetHashCode(Hsv obj)
{
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(Lms x, Lms y)
{
@ -157,6 +208,63 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(YCbCr x, YCbCr y)
{
return this.Equals(x.Y, y.Y)
&& this.Equals(x.Cb, y.Cb)
&& this.Equals(x.Cr, y.Cr);
}
/// <inheritdoc/>
public int GetHashCode(YCbCr obj)
{
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(CieXyChromaticityCoordinates x, CieXyChromaticityCoordinates y)
{
return this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y);
}
/// <inheritdoc/>
public int GetHashCode(CieXyChromaticityCoordinates obj)
{
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(RgbPrimariesChromaticityCoordinates x, RgbPrimariesChromaticityCoordinates y)
{
return this.Equals(x.R, y.R) && this.Equals(x.G, y.G) && this.Equals(x.B, y.B);
}
/// <inheritdoc/>
public int GetHashCode(RgbPrimariesChromaticityCoordinates obj)
{
return obj.GetHashCode();
}
/// <inheritdoc/>
public bool Equals(RgbWorkingSpace x, RgbWorkingSpace y)
{
if (x is RgbWorkingSpace g1 && y is RgbWorkingSpace g2)
{
return this.Equals(g1.WhitePoint, g2.WhitePoint)
&& this.Equals(g1.ChromaticityCoordinates, g2.ChromaticityCoordinates);
}
return this.Equals(x.WhitePoint, y.WhitePoint)
&& this.Equals(x.ChromaticityCoordinates, y.ChromaticityCoordinates);
}
/// <inheritdoc/>
public int GetHashCode(RgbWorkingSpace obj)
{
return obj.GetHashCode();
}
private bool Equals(float x, float y)
{
float d = x - y;

23
tests/ImageSharp.Tests/Colorspaces/CieLabAndCieLchConversionTests.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -37,11 +38,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var input = new CieLch(l, c, h);
var expected = new CieLab(l2, a, b);
Span<CieLch> inputSpan = new CieLch[5];
inputSpan.Fill(input);
Span<CieLab> actualSpan = new CieLab[5];
// Act
var actual = Converter.ToCieLab(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -62,11 +74,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var input = new CieLab(l, a, b);
var expected = new CieLch(l2, c, h);
Span<CieLab> inputSpan = new CieLab[5];
inputSpan.Fill(input);
Span<CieLch> actualSpan = new CieLch[5];
// Act
var actual = Converter.ToCieLch(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

24
tests/ImageSharp.Tests/Colorspaces/CieLuvAndCieLchuvConversionTests.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -37,11 +38,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var input = new CieLchuv(l, c, h);
var expected = new CieLuv(l2, u, v);
Span<CieLchuv> inputSpan = new CieLchuv[5];
inputSpan.Fill(input);
Span<CieLuv> actualSpan = new CieLuv[5];
// Act
var actual = Converter.ToCieLuv(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -63,11 +75,23 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var input = new CieLuv(l, u, v);
var expected = new CieLchuv(l2, c, h);
Span<CieLuv> inputSpan = new CieLuv[5];
inputSpan.Fill(input);
Span<CieLchuv> actualSpan = new CieLchuv[5];
// Act
var actual = Converter.ToCieLchuv(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

23
tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieLabConversionTest.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -37,11 +38,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 };
var expected = new CieXyz(x, y, z);
Span<CieLab> inputSpan = new CieLab[5];
inputSpan.Fill(input);
Span<CieXyz> actualSpan = new CieXyz[5];
// Act
var actual = converter.ToCieXyz(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -61,11 +73,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 };
var expected = new CieLab(l, a, b);
Span<CieXyz> inputSpan = new CieXyz[5];
inputSpan.Fill(input);
Span<CieLab> actualSpan = new CieLab[5];
// Act
var actual = converter.ToCieLab(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

23
tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieLuvConversionTest.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -36,11 +37,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 };
var expected = new CieXyz(x, y, z);
Span<CieLuv> inputSpan = new CieLuv[5];
inputSpan.Fill(input);
Span<CieXyz> actualSpan = new CieXyz[5];
// Act
var actual = converter.ToCieXyz(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -60,11 +72,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 };
var expected = new CieLuv(l, u, v);
Span<CieXyz> inputSpan = new CieXyz[5];
inputSpan.Fill(input);
Span<CieLuv> actualSpan = new CieLuv[5];
// Act
var actual = converter.ToCieLuv(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

24
tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieXyyConversionTest.cs

@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -30,11 +30,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var input = new CieXyy(x, y, yl);
var expected = new CieXyz(xyzX, xyzY, xyzZ);
Span<CieXyy> inputSpan = new CieXyy[5];
inputSpan.Fill(input);
Span<CieXyz> actualSpan = new CieXyz[5];
// Act
var actual = Converter.ToCieXyz(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
[Theory]
@ -47,11 +58,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var input = new CieXyz(xyzX, xyzY, xyzZ);
var expected = new CieXyy(x, y, yl);
Span<CieXyz> inputSpan = new CieXyz[5];
inputSpan.Fill(input);
Span<CieXyy> actualSpan = new CieXyy[5];
// Act
var actual = Converter.ToCieXyy(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

34
tests/ImageSharp.Tests/Colorspaces/CieXyzAndHunterLabConversionTest.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -31,11 +32,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.C };
var expected = new CieXyz(x, y, z);
Span<HunterLab> inputSpan = new HunterLab[5];
inputSpan.Fill(input);
Span<CieXyz> actualSpan = new CieXyz[5];
// Act
var actual = converter.ToCieXyz(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -51,11 +63,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
var expected = new CieXyz(x, y, z);
Span<HunterLab> inputSpan = new HunterLab[5];
inputSpan.Fill(input);
Span<CieXyz> actualSpan = new CieXyz[5];
// Act
var actual = converter.ToCieXyz(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -71,11 +94,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
var expected = new HunterLab(l, a, b);
Span<CieXyz> inputSpan = new CieXyz[5];
inputSpan.Fill(input);
Span<HunterLab> actualSpan = new HunterLab[5];
// Act
var actual = converter.ToHunterLab(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

13
tests/ImageSharp.Tests/Colorspaces/CieXyzAndLmsConversionTest.cs

@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -35,11 +35,22 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
var converter = new ColorSpaceConverter();
var expected = new CieXyz(x, y, z);
Span<Lms> inputSpan = new Lms[5];
inputSpan.Fill(input);
Span<CieXyz> actualSpan = new CieXyz[5];
// Act
var actual = converter.ToCieXyz(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>

5
tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs

@ -16,7 +16,6 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
/// </summary>
public class ColorConverterAdaptTest
{
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(.0001F);
private static readonly ApproximateColorSpaceComparer ColorSpaceComparer = new ApproximateColorSpaceComparer(.0001F);
[Theory]
@ -34,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb actual = converter.Adapt(input);
// Assert
Assert.Equal(expected.WorkingSpace, actual.WorkingSpace, ApproximateComparer);
Assert.Equal(expected.WorkingSpace, actual.WorkingSpace, ColorSpaceComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
}
@ -53,7 +52,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
Rgb actual = converter.Adapt(input);
// Assert
Assert.Equal(expected.WorkingSpace, actual.WorkingSpace, ApproximateComparer);
Assert.Equal(expected.WorkingSpace, actual.WorkingSpace, ColorSpaceComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
}

87
tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs

@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -17,9 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
/// </remarks>
public class RgbAndCieXyzConversionTest
{
private static readonly IEqualityComparer<float> FloatRoundingComparer = new FloatRoundingComparer(5);
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
private static readonly ApproximateColorSpaceComparer ColorSpaceComparer = new ApproximateColorSpaceComparer(.0001F);
/// <summary>
/// Tests conversion from <see cref="CieXyz"/> (<see cref="Illuminants.D50"/>)
@ -37,17 +35,25 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
// Arrange
var input = new CieXyz(x, y, z);
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb };
var expected = new Rgb(r, g, b);
Span<CieXyz> inputSpan = new CieXyz[5];
inputSpan.Fill(input);
Span<Rgb> actualSpan = new Rgb[5];
// Act
Rgb output = converter.ToRgb(input);
var actual = converter.ToRgb(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
IEqualityComparer<float> comparer = new ApproximateFloatComparer(0.001f);
Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, comparer);
Assert.Equal(g, output.G, comparer);
Assert.Equal(b, output.B, comparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -65,17 +71,27 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_XYZ_D65_to_SRGB(float x, float y, float z, float r, float g, float b)
{
// Arrange
CieXyz input = new CieXyz(x, y, z);
ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb };
var input = new CieXyz(x, y, z);
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb };
var expected = new Rgb(r, g, b);
Span<CieXyz> inputSpan = new CieXyz[5];
inputSpan.Fill(input);
Span<Rgb> actualSpan = new Rgb[5];
// Act
Rgb output = converter.ToRgb(input);
var actual = converter.ToRgb(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);
Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -94,15 +110,24 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
// Arrange
var input = new Rgb(r, g, b);
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50 };
var expected = new CieXyz(x, y, z);
Span<Rgb> inputSpan = new Rgb[5];
inputSpan.Fill(input);
Span<CieXyz> actualSpan = new CieXyz[5];
// Act
CieXyz output = converter.ToCieXyz(input);
var actual = converter.ToCieXyz(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
IEqualityComparer<float> comparer = new ApproximateFloatComparer(0.001f);
Assert.Equal(x, output.X, comparer);
Assert.Equal(y, output.Y, comparer);
Assert.Equal(z, output.Z, comparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -121,14 +146,24 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
// Arrange
var input = new Rgb(r, g, b);
var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
var expected = new CieXyz(x, y, z);
Span<Rgb> inputSpan = new Rgb[5];
inputSpan.Fill(input);
Span<CieXyz> actualSpan = new CieXyz[5];
// Act
CieXyz output = converter.ToCieXyz(input);
var actual = converter.ToCieXyz(input);
converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(x, output.X, FloatRoundingComparer);
Assert.Equal(y, output.Y, FloatRoundingComparer);
Assert.Equal(z, output.Z, FloatRoundingComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

46
tests/ImageSharp.Tests/Colorspaces/RgbAndCmykConversionTest.cs

@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -18,11 +18,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
/// </remarks>
public class RgbAndCmykConversionTest
{
private static readonly IEqualityComparer<float> FloatRoundingComparer = new FloatRoundingComparer(4);
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
private static readonly ApproximateColorSpaceComparer ColorSpaceComparer = new ApproximateColorSpaceComparer(.0001F);
/// <summary>
/// Tests conversion from <see cref="Cmyk"/> to <see cref="Rgb"/>.
@ -35,15 +32,25 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
// Arrange
var input = new Cmyk(c, m, y, k);
var expected = new Rgb(r, g, b);
Span<Cmyk> inputSpan = new Cmyk[5];
inputSpan.Fill(input);
Span<Rgb> actualSpan = new Rgb[5];
// Act
var output = Converter.ToRgb(input);
var actual = Converter.ToRgb(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);
Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -57,15 +64,24 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
// Arrange
var input = new Rgb(r, g, b);
var expected = new Cmyk(c, m, y, k);
Span<Rgb> inputSpan = new Rgb[5];
inputSpan.Fill(input);
Span<Cmyk> actualSpan = new Cmyk[5];
// Act
var output = Converter.ToCmyk(input);
var actual = Converter.ToCmyk(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(c, output.C, FloatRoundingComparer);
Assert.Equal(m, output.M, FloatRoundingComparer);
Assert.Equal(y, output.Y, FloatRoundingComparer);
Assert.Equal(k, output.K, FloatRoundingComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

46
tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs

@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -18,11 +18,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
/// </remarks>
public class RgbAndHslConversionTest
{
private static readonly IEqualityComparer<float> FloatRoundingComparer = new FloatRoundingComparer(4);
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
private static readonly ApproximateColorSpaceComparer ColorSpaceComparer = new ApproximateColorSpaceComparer(.0001F);
/// <summary>
/// Tests conversion from <see cref="Hsl"/> to <see cref="Rgb"/>.
@ -38,15 +35,25 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
// Arrange
var input = new Hsl(h, s, l);
var expected = new Rgb(r, g, b);
Span<Hsl> inputSpan = new Hsl[5];
inputSpan.Fill(input);
Span<Rgb> actualSpan = new Rgb[5];
// Act
Rgb output = Converter.ToRgb(input);
var actual = Converter.ToRgb(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);
Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -62,14 +69,25 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
// Arrange
var input = new Rgb(r, g, b);
var expected = new Hsl(h, s, l);
Span<Rgb> inputSpan = new Rgb[5];
inputSpan.Fill(input);
Span<Hsl> actualSpan = new Hsl[5];
// Act
Hsl output = Converter.ToHsl(input);
var actual = Converter.ToHsl(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(h, output.H, FloatRoundingComparer);
Assert.Equal(s, output.S, FloatRoundingComparer);
Assert.Equal(l, output.L, FloatRoundingComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

45
tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs

@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -17,11 +17,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
/// </remarks>
public class RgbAndHsvConversionTest
{
private static readonly IEqualityComparer<float> FloatRoundingComparer = new FloatRoundingComparer(4);
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
private static readonly ApproximateColorSpaceComparer ColorSpaceComparer = new ApproximateColorSpaceComparer(.0001F);
/// <summary>
/// Tests conversion from <see cref="Hsv"/> to <see cref="Rgb"/>.
@ -37,15 +34,25 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
// Arrange
var input = new Hsv(h, s, v);
var expected = new Rgb(r, g, b);
Span<Hsv> inputSpan = new Hsv[5];
inputSpan.Fill(input);
Span<Rgb> actualSpan = new Rgb[5];
// Act
Rgb output = Converter.ToRgb(input);
var actual = Converter.ToRgb(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);
Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -61,14 +68,24 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
// Arrange
var input = new Rgb(r, g, b);
var expected = new Hsv(h, s, v);
Span<Rgb> inputSpan = new Rgb[5];
inputSpan.Fill(input);
Span<Hsv> actualSpan = new Hsv[5];
// Act
Hsv output = Converter.ToHsv(input);
var actual = Converter.ToHsv(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(h, output.H, FloatRoundingComparer);
Assert.Equal(s, output.S, FloatRoundingComparer);
Assert.Equal(v, output.V, FloatRoundingComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

45
tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs

@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using Xunit;
@ -16,11 +16,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
/// </remarks>
public class RgbAndYCbCrConversionTest
{
private static readonly IEqualityComparer<float> FloatRoundingComparer = new FloatRoundingComparer(3);
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
private static readonly ApproximateFloatComparer ApproximateComparer = new ApproximateFloatComparer(0.0001F);
private static readonly ApproximateColorSpaceComparer ColorSpaceComparer = new ApproximateColorSpaceComparer(.001F);
/// <summary>
/// Tests conversion from <see cref="YCbCr"/> to <see cref="Rgb"/>.
@ -33,15 +30,25 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
// Arrange
var input = new YCbCr(y, cb, cr);
var expected = new Rgb(r, g, b);
Span<YCbCr> inputSpan = new YCbCr[5];
inputSpan.Fill(input);
Span<Rgb> actualSpan = new Rgb[5];
// Act
Rgb output = Converter.ToRgb(input);
var actual = Converter.ToRgb(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace, ApproximateComparer);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);
Assert.Equal(Rgb.DefaultWorkingSpace, actual.WorkingSpace, ColorSpaceComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
/// <summary>
@ -56,14 +63,24 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{
// Arrange
var input = new Rgb(r, g, b);
var expected = new YCbCr(y, cb, cr);
Span<Rgb> inputSpan = new Rgb[5];
inputSpan.Fill(input);
Span<YCbCr> actualSpan = new YCbCr[5];
// Act
YCbCr output = Converter.ToYCbCr(input);
var actual = Converter.ToYCbCr(input);
Converter.Convert(inputSpan, actualSpan, actualSpan.Length);
// Assert
Assert.Equal(y, output.Y, FloatRoundingComparer);
Assert.Equal(cb, output.Cb, FloatRoundingComparer);
Assert.Equal(cr, output.Cr, FloatRoundingComparer);
Assert.Equal(expected, actual, ColorSpaceComparer);
for (int i = 0; i < actualSpan.Length; i++)
{
Assert.Equal(expected, actualSpan[i], ColorSpaceComparer);
}
}
}
}

76
tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs

@ -4,36 +4,37 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.Tests
{
internal struct ApproximateFloatComparer :
/// <summary>
/// Allows the approximate comparison of single precision floating point values.
/// </summary>
internal readonly struct ApproximateFloatComparer :
IEqualityComparer<float>,
IEqualityComparer<Vector4>,
IEqualityComparer<CieXyChromaticityCoordinates>,
IEqualityComparer<RgbPrimariesChromaticityCoordinates>,
IEqualityComparer<CieXyz>,
IEqualityComparer<RgbWorkingSpace>
IEqualityComparer<Vector4>
{
private readonly float Eps;
private readonly float Epsilon;
public ApproximateFloatComparer(float eps = 1f)
/// <summary>
/// Initializes a new instance of the <see cref="ApproximateFloatComparer"/> class.
/// </summary>
/// <param name="epsilon">The comparison error difference epsilon to use.</param>
public ApproximateFloatComparer(float epsilon = 1f)
{
this.Eps = eps;
this.Epsilon = epsilon;
}
public bool Equals(float x, float y)
{
float d = x - y;
return d >= -this.Eps && d <= this.Eps;
return d >= -this.Epsilon && d <= this.Epsilon;
}
public int GetHashCode(float obj)
{
throw new InvalidOperationException();
return obj.GetHashCode();
}
public bool Equals(Vector4 x, Vector4 y)
@ -43,54 +44,7 @@ namespace SixLabors.ImageSharp.Tests
public int GetHashCode(Vector4 obj)
{
throw new InvalidOperationException();
}
public bool Equals(CieXyChromaticityCoordinates x, CieXyChromaticityCoordinates y)
{
return this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y);
}
public int GetHashCode(CieXyChromaticityCoordinates obj)
{
throw new NotImplementedException();
}
public bool Equals(RgbPrimariesChromaticityCoordinates x, RgbPrimariesChromaticityCoordinates y)
{
return this.Equals(x.R, y.R) && this.Equals(x.G, y.G) && this.Equals(x.B, y.B);
}
public int GetHashCode(RgbPrimariesChromaticityCoordinates obj)
{
throw new NotImplementedException();
}
public bool Equals(CieXyz x, CieXyz y)
{
return this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y) && this.Equals(x.Z, y.Z);
}
public int GetHashCode(CieXyz obj)
{
throw new NotImplementedException();
}
public bool Equals(RgbWorkingSpace x, RgbWorkingSpace y)
{
if (x is RgbWorkingSpace g1 && y is RgbWorkingSpace g2)
{
return this.Equals(g1.WhitePoint, g2.WhitePoint)
&& this.Equals(g1.ChromaticityCoordinates, g2.ChromaticityCoordinates);
}
return this.Equals(x.WhitePoint, y.WhitePoint)
&& this.Equals(x.ChromaticityCoordinates, y.ChromaticityCoordinates);
}
public int GetHashCode(RgbWorkingSpace obj)
{
throw new NotImplementedException();
return obj.GetHashCode();
}
}
}

68
tests/ImageSharp.Tests/TestUtilities/FloatRoundingComparer.cs

@ -1,68 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.Numerics;
namespace SixLabors.ImageSharp.Tests
{
/// <summary>
/// Allows the comparison of single-precision floating point values by precision.
/// </summary>
public struct FloatRoundingComparer : IEqualityComparer<float>, IEqualityComparer<Vector4>
{
/// <summary>
/// Initializes a new instance of the <see cref="FloatRoundingComparer"/> struct.
/// </summary>
/// <param name="precision">The number of decimal places (valid values: 0-7)</param>
public FloatRoundingComparer(int precision)
{
Guard.MustBeBetweenOrEqualTo(precision, 0, 7, nameof(precision));
this.Precision = precision;
}
/// <summary>
/// Gets the number of decimal places (valid values: 0-7)
/// </summary>
public int Precision { get; }
/// <inheritdoc />
public bool Equals(float x, float y)
{
float xp = (float)Math.Round(x, this.Precision, MidpointRounding.AwayFromZero);
float yp = (float)Math.Round(y, this.Precision, MidpointRounding.AwayFromZero);
// ReSharper disable once CompareOfFloatsByEqualityOperator
return xp == yp;
}
/// <inheritdoc />
public bool Equals(Vector4 x, Vector4 y)
{
return this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y) && this.Equals(x.Z, y.Z) && this.Equals(x.W, y.W);
}
/// <inheritdoc />
public int GetHashCode(float obj)
{
unchecked
{
int hashCode = obj.GetHashCode();
hashCode = (hashCode * 397) ^ this.Precision.GetHashCode();
return hashCode;
}
}
/// <inheritdoc />
public int GetHashCode(Vector4 obj)
{
unchecked
{
int hashCode = obj.GetHashCode();
hashCode = (hashCode * 397) ^ this.Precision.GetHashCode();
return hashCode;
}
}
}
}
Loading…
Cancel
Save