Browse Source

Add Hsl

af/merge-core
James Jackson-South 9 years ago
parent
commit
f3159e4429
  1. 11
      src/ImageSharp/Colors/Spaces/Cmyk.cs
  2. 13
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLab.cs
  3. 13
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLch.cs
  4. 16
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyy.cs
  5. 15
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyz.cs
  6. 14
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Cmyk.cs
  7. 142
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Hsl.cs
  8. 13
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.HunterLab.cs
  9. 13
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.LinearRgb.cs
  10. 13
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Lms.cs
  11. 13
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Rgb.cs
  12. 153
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs
  13. 157
      src/ImageSharp/Colors/Spaces/Hsl.cs
  14. 7
      tests/ImageSharp.Tests/Colors/Colorspaces/ColorSpaceEqualityTests.cs
  15. 2
      tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCmykConversionTest.cs
  16. 72
      tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndHslConversionTest.cs

11
src/ImageSharp/Colors/Spaces/Cmyk.cs

@ -32,9 +32,18 @@ namespace ImageSharp.Colors.Spaces
/// <param name="y">The yellow component.</param>
/// <param name="k">The keyline black component.</param>
public Cmyk(float c, float m, float y, float k)
: this(new Vector4(c, m, y, k))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
/// </summary>
/// <param name="vector">The vector representing the c, m, y, k components.</param>
public Cmyk(Vector4 vector)
: this()
{
this.backingVector = Vector4.Clamp(new Vector4(c, m, y, k), Vector4.Zero, Vector4.One);
this.backingVector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
}
/// <summary>

13
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLab.cs

@ -85,6 +85,19 @@ namespace ImageSharp.Colors.Spaces.Conversion
return this.ToCieLab(xyzColor);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="CieLab"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(Hsl color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="CieLab"/>
/// </summary>

13
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLch.cs

@ -72,6 +72,19 @@ namespace ImageSharp.Colors.Spaces.Conversion
return this.ToCieLch(xyzColor);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="CieLch"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="CieLch"/></returns>
public CieLch ToCieLch(Hsl color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLch(xyzColor);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="CieLch"/>
/// </summary>

16
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyy.cs

@ -58,7 +58,7 @@ namespace ImageSharp.Colors.Spaces.Conversion
/// Converts a <see cref="Cmyk"/> into a <see cref="CieXyy"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Cmyk"/></returns>
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(Cmyk color)
{
Guard.NotNull(color, nameof(color));
@ -68,6 +68,20 @@ namespace ImageSharp.Colors.Spaces.Conversion
return this.ToCieXyy(xyzColor);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="CieXyy"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(Hsl color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="CieXyy"/>
/// </summary>

15
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyz.cs

@ -85,6 +85,21 @@ namespace ImageSharp.Colors.Spaces.Conversion
return this.ToCieXyz(rgb);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="CieXyz"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="CieXyz"/></returns>
public CieXyz ToCieXyz(Hsl color)
{
Guard.NotNull(color, nameof(color));
// Conversion
Rgb rgb = this.ToRgb(color);
return this.ToCieXyz(rgb);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="CieXyz"/>
/// </summary>

14
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Cmyk.cs

@ -71,6 +71,20 @@ namespace ImageSharp.Colors.Spaces.Conversion
return CmykAndRgbConverter.Convert(rgb);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="Cmyk"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(Hsl color)
{
Guard.NotNull(color, nameof(color));
Rgb rgb = this.ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="Cmyk"/>
/// </summary>

142
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Hsl.cs

@ -0,0 +1,142 @@
// <copyright file="ColorSpaceConverter.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion
{
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion.Implementation.Hsl;
/// <summary>
/// Converts between color spaces ensuring that the color is adapted using chromatic adaptation.
/// </summary>
public partial class ColorSpaceConverter
{
private static readonly HslAndRgbConverter HslAndRgbConverter = new HslAndRgbConverter();
/// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(CieLab color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
/// <summary>
/// Converts a <see cref="CieLch"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(CieLch color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
/// <summary>
/// Converts a <see cref="CieXyy"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(CieXyy color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
/// <summary>
/// Converts a <see cref="CieXyz"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(CieXyz color)
{
Guard.NotNull(color, nameof(color));
Rgb rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
}
/// <summary>
/// Converts a <see cref="Cmyk"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(Cmyk color)
{
Guard.NotNull(color, nameof(color));
Rgb rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(HunterLab color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
/// <summary>
/// Converts a <see cref="LinearRgb"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(LinearRgb color)
{
Guard.NotNull(color, nameof(color));
Rgb rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
}
/// <summary>
/// Converts a <see cref="Lms"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(Lms color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
/// <summary>
/// Converts a <see cref="Rgb"/> into a <see cref="Hsl"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(Rgb color)
{
Guard.NotNull(color, nameof(color));
return HslAndRgbConverter.Convert(color);
}
}
}

13
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.HunterLab.cs

@ -82,6 +82,19 @@ namespace ImageSharp.Colors.Spaces.Conversion
return this.ToHunterLab(xyzColor);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="HunterLab"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="HunterLab"/></returns>
public HunterLab ToHunterLab(Hsl color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
/// <summary>
/// Converts a <see cref="LinearRgb"/> into a <see cref="HunterLab"/>
/// </summary>

13
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.LinearRgb.cs

@ -87,6 +87,19 @@ namespace ImageSharp.Colors.Spaces.Conversion
return this.ToLinearRgb(rgb);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="LinearRgb"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(Hsl color)
{
Guard.NotNull(color, nameof(color));
Rgb rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="LinearRgb"/>
/// </summary>

13
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Lms.cs

@ -77,6 +77,19 @@ namespace ImageSharp.Colors.Spaces.Conversion
return this.ToLms(xyzColor);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="Lms"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Lms"/></returns>
public Lms ToLms(Hsl color)
{
Guard.NotNull(color, nameof(color));
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="Lms"/>
/// </summary>

13
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Rgb.cs

@ -82,6 +82,19 @@ namespace ImageSharp.Colors.Spaces.Conversion
return CmykAndRgbConverter.Convert(color);
}
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="Rgb"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(Hsl color)
{
Guard.NotNull(color, nameof(color));
// Conversion
return HslAndRgbConverter.Convert(color);
}
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="Rgb"/>
/// </summary>

153
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Hsl/HslAndRgbConverter.cs

@ -0,0 +1,153 @@
// <copyright file="HslAndRgbConverter.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Hsl
{
using System.Runtime.CompilerServices;
using ImageSharp.Colors.Spaces;
/// <summary>
/// Color converter between HSL and Rgb
/// See <see href="http://www.poynton.com/PDFs/coloureq.pdf"/> for formulas.
/// </summary>
internal class HslAndRgbConverter : IColorConversion<Hsl, Rgb>, IColorConversion<Rgb, Hsl>
{
/// <inheritdoc/>
public Rgb Convert(Hsl input)
{
float rangedH = input.H / 360F;
float r = 0;
float g = 0;
float b = 0;
float s = input.S;
float l = input.L;
if (MathF.Abs(l) > Constants.Epsilon)
{
if (MathF.Abs(s) < Constants.Epsilon)
{
r = g = b = l;
}
else
{
float temp2 = (l < .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 Rgb(r, g, b);
}
/// <inheritdoc/>
public Hsl Convert(Rgb input)
{
float r = input.R;
float g = input.G;
float b = input.B;
float max = MathF.Max(r, MathF.Max(g, b));
float min = MathF.Min(r, MathF.Min(g, b));
float chroma = max - min;
float h = 0F;
float s = 0F;
float l = (max + min) / 2F;
if (MathF.Abs(chroma) < Constants.Epsilon)
{
return new Hsl(0F, s, l);
}
if (MathF.Abs(r - max) < Constants.Epsilon)
{
h = (g - b) / chroma;
}
else if (MathF.Abs(g - max) < Constants.Epsilon)
{
h = 2F + ((b - r) / chroma);
}
else if (MathF.Abs(b - max) < Constants.Epsilon)
{
h = 4F + ((r - g) / chroma);
}
h *= 60F;
if (h < 0F)
{
h += 360F;
}
if (l <= .5F)
{
s = chroma / (max + min);
}
else
{
s = chroma / (2F - chroma);
}
return new Hsl(h, s, l);
}
/// <summary>
/// Gets the color component from the given values.
/// </summary>
/// <param name="first">The first value.</param>
/// <param name="second">The second value.</param>
/// <param name="third">The third value.</param>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float GetColorComponent(float first, float second, float third)
{
third = MoveIntoRange(third);
if (third < 0.1666667F)
{
return first + ((second - first) * 6F * third);
}
if (third < .5F)
{
return second;
}
if (third < 0.6666667F)
{
return first + ((second - first) * (0.6666667F - third) * 6F);
}
return first;
}
/// <summary>
/// Moves the specific value within the acceptable range for
/// conversion.
/// <remarks>Used for converting <see cref="Hsl"/> colors to this type.</remarks>
/// </summary>
/// <param name="value">The value to shift.</param>
/// <returns>
/// The <see cref="float"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float MoveIntoRange(float value)
{
if (value < 0F)
{
value += 1F;
}
else if (value > 1F)
{
value -= 1F;
}
return value;
}
}
}

157
src/ImageSharp/Colors/Spaces/Hsl.cs

@ -0,0 +1,157 @@
// <copyright file="Hsl.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
using System.Numerics;
/// <summary>
/// Represents a Hsl (hue, saturation, lightness) color.
/// </summary>
public struct Hsl : IColorVector, IEquatable<Hsl>, IAlmostEquatable<Hsl, float>
{
/// <summary>
/// Represents a <see cref="Hsl"/> that has H, S, and L values set to zero.
/// </summary>
public static readonly Hsl Empty = default(Hsl);
/// <summary>
/// Max range used for clamping
/// </summary>
private static readonly Vector3 VectorMax = new Vector3(360, 1, 1);
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private readonly Vector3 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="Hsl"/> struct.
/// </summary>
/// <param name="h">The h hue component.</param>
/// <param name="s">The s saturation component.</param>
/// <param name="l">The l value (lightness) component.</param>
public Hsl(float h, float s, float l)
: this(new Vector3(h, s, l))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Hsl"/> struct.
/// </summary>
/// <param name="vector">The vector representing the h, s, l components.</param>
public Hsl(Vector3 vector)
{
this.backingVector = Vector3.Clamp(vector, Vector3.Zero, VectorMax);
}
/// <summary>
/// Gets the hue component.
/// <remarks>A value ranging between 0 and 360.</remarks>
/// </summary>
public float H => this.backingVector.X;
/// <summary>
/// Gets the saturation component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public float S => this.backingVector.Y;
/// <summary>
/// Gets the lightness component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public float L => this.backingVector.Z;
/// <summary>
/// Gets a value indicating whether this <see cref="Hsl"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
/// <inheritdoc/>
public Vector3 Vector => this.backingVector;
/// <summary>
/// Compares two <see cref="Hsl"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="Hsl"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="Hsl"/> 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>
public static bool operator ==(Hsl left, Hsl right)
{
return left.Equals(right);
}
/// <summary>
/// Compares two <see cref="Hsl"/> objects for inequality.
/// </summary>
/// <param name="left">
/// The <see cref="Hsl"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="Hsl"/> 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>
public static bool operator !=(Hsl left, Hsl right)
{
return !left.Equals(right);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
public override string ToString()
{
if (this.IsEmpty)
{
return "Hsl [ Empty ]";
}
return $"Hsl [ H={this.H:#0.##}, S={this.S:#0.##}, L={this.L:#0.##} ]";
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is Hsl)
{
return this.Equals((Hsl)obj);
}
return false;
}
/// <inheritdoc/>
public bool Equals(Hsl other)
{
return this.backingVector.Equals(other.backingVector);
}
/// <inheritdoc/>
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;
}
}
}

7
tests/ImageSharp.Tests/Colors/Colorspaces/ColorSpaceEqualityTests.cs

@ -27,6 +27,7 @@ namespace ImageSharp.Tests.Colors
Lms.Empty,
LinearRgb.Empty,
Rgb.Empty,
Hsl.Empty
};
public static readonly TheoryData<object, object, Type> EqualityData =
@ -40,6 +41,7 @@ namespace ImageSharp.Tests.Colors
{ new Lms(Vector3.One), new Lms(Vector3.One), typeof(Lms) },
{ new LinearRgb(Vector3.One), new LinearRgb(Vector3.One), typeof(LinearRgb) },
{ new Rgb(Vector3.One), new Rgb(Vector3.One), typeof(Rgb) },
{ new Hsl(Vector3.One), new Hsl(Vector3.One), typeof(Hsl) },
};
public static readonly TheoryData<object, object, Type> NotEqualityDataNulls =
@ -54,6 +56,7 @@ namespace ImageSharp.Tests.Colors
{ new Lms(Vector3.One), null, typeof(Lms) },
{ new LinearRgb(Vector3.One), null, typeof(LinearRgb) },
{ new Rgb(Vector3.One), null, typeof(Rgb) },
{ new Hsl(Vector3.One), null, typeof(Hsl) },
};
public static readonly TheoryData<object, object, Type> NotEqualityDataDifferentObjects =
@ -64,6 +67,7 @@ namespace ImageSharp.Tests.Colors
{ new CieXyz(Vector3.One), new HunterLab(Vector3.Zero), null },
{ new Rgb(Vector3.One), new LinearRgb(Vector3.Zero), null },
{ new Rgb(Vector3.One), new Lms(Vector3.Zero), null },
{ new Cmyk(Vector4.One), new Hsl(Vector3.Zero), null },
};
public static readonly TheoryData<object, object, Type> NotEqualityData =
@ -78,6 +82,8 @@ namespace ImageSharp.Tests.Colors
{ new Lms(Vector3.One), new Lms(Vector3.Zero), typeof(Lms) },
{ new LinearRgb(Vector3.One), new LinearRgb(Vector3.Zero), typeof(LinearRgb) },
{ new Rgb(Vector3.One), new Rgb(Vector3.Zero), typeof(Rgb) },
{ new Cmyk(Vector4.One), new Cmyk(Vector4.Zero), typeof(Cmyk) },
{ new Hsl(Vector3.One), new Hsl(Vector3.Zero), typeof(Hsl) },
};
public static readonly TheoryData<object, object, Type, float> AlmostEqualsData =
@ -94,6 +100,7 @@ namespace ImageSharp.Tests.Colors
{ 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(1, 1, 1, 1), new Cmyk(1, 1, 1, .99F), typeof(Cmyk), .01F },
};
public static readonly TheoryData<object, object, Type, float> AlmostNotEqualsData =

2
tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCmykConversionTest.cs

@ -8,7 +8,7 @@
using Xunit;
/// <summary>
/// Tests <see cref="CieXyz"/>-<see cref="CieLab"/> conversions.
/// Tests <see cref="Rgb"/>-<see cref="Cmyk"/> conversions.
/// </summary>
/// <remarks>
/// Test data generated using:

72
tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndHslConversionTest.cs

@ -0,0 +1,72 @@
namespace ImageSharp.Tests.Colors.Colorspaces
{
using System.Collections.Generic;
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion;
using Xunit;
/// <summary>
/// Tests <see cref="Rgb"/>-<see cref="Hsl"/> conversions.
/// </summary>
/// <remarks>
/// Test data generated using:
/// <see href="http://www.colorhexa.com"/>
/// <see href="http://www.rapidtables.com/convert/color/hsl-to-rgb"/>
/// </remarks>
public class RgbAndHslConversionTest
{
private static readonly IEqualityComparer<float> FloatRoundingComparer = new FloatRoundingComparer(4);
private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
/// <summary>
/// Tests conversion from <see cref="Hsl"/> to <see cref="Rgb"/>.
/// </summary>
[Theory]
[InlineData(0, 0, 0, 0, 0, 0)]
[InlineData(0, 1, 1, 1, 1, 1)]
[InlineData(360, 1, 1, 1, 1, 1)]
[InlineData(0, 1, .5F, 1, 0, 0)]
[InlineData(120, 1, .5F, 0, 1, 0)]
[InlineData(240, 1, .5F, 0, 0, 1)]
public void Convert_Hsl_To_Rgb(float h, float s, float l, float r, float g, float b)
{
// Arrange
Hsl input = new Hsl(h, s, l);
// Act
Rgb output = Converter.ToRgb(input);
// Assert
Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
Assert.Equal(r, output.R, FloatRoundingComparer);
Assert.Equal(g, output.G, FloatRoundingComparer);
Assert.Equal(b, output.B, FloatRoundingComparer);
}
/// <summary>
/// Tests conversion from <see cref="Rgb"/> to <see cref="Hsl"/>.
/// </summary>
[Theory]
[InlineData(0, 0, 0, 0, 0, 0)]
[InlineData(1, 1, 1, 0, 0, 1)]
[InlineData(1, 0, 0, 0, 1, .5F)]
[InlineData(0, 1, 0, 120, 1, .5F)]
[InlineData(0, 0, 1, 240, 1, .5F)]
public void Convert_Rgb_To_Hsl(float r, float g, float b, float h, float s, float l)
{
// Arrange
Rgb input = new Rgb(r, g, b);
// Act
Hsl output = Converter.ToHsl(input);
// Assert
Assert.Equal(h, output.H, FloatRoundingComparer);
Assert.Equal(s, output.S, FloatRoundingComparer);
Assert.Equal(l, output.L, FloatRoundingComparer);
}
}
}
Loading…
Cancel
Save