Browse Source

Replace ICompanding with static methods.

af/merge-core
James Jackson-South 7 years ago
parent
commit
f6f093eef2
  1. 2
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
  2. 2
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs
  3. 2
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs
  4. 35
      src/ImageSharp/ColorSpaces/Conversion/ICompanding.cs
  5. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs
  6. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs
  7. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
  8. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs
  9. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs
  10. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
  11. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
  12. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndHunterLabConverterBase.cs
  13. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs
  14. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs
  15. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLuvConverter.cs
  16. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToHunterLabConverter.cs
  17. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs
  18. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
  19. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs
  20. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs
  21. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
  22. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs
  23. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs
  24. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
  25. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
  26. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
  27. 37
      src/ImageSharp/ColorSpaces/Conversion/Implementation/GammaCompanding.cs
  28. 33
      src/ImageSharp/ColorSpaces/Conversion/Implementation/LCompanding.cs
  29. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs
  30. 27
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rec709Companding.cs
  31. 90
      src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbWorkingSpace.cs
  32. 33
      src/ImageSharp/ColorSpaces/Conversion/Implementation/SRgbCompanding.cs
  33. 36
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaCompanding.cs
  34. 65
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
  35. 37
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LCompanding.cs
  36. 31
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs
  37. 18
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020Companding.cs
  38. 31
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs
  39. 35
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709Companding.cs
  40. 31
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs
  41. 83
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs
  42. 35
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbCompanding.cs
  43. 31
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs
  44. 10
      src/ImageSharp/ColorSpaces/LinearRgb.cs
  45. 10
      src/ImageSharp/ColorSpaces/Rgb.cs
  46. 38
      src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs
  47. 21
      tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs
  48. 31
      tests/ImageSharp.Tests/Colorspaces/Conversion/CompandingTests.cs
  49. 25
      tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs

2
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs

@ -470,7 +470,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="workingSpace">The source working space</param>
/// <returns>The <see cref="LinearRgbToCieXyzConverter"/></returns>
private LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace)
private LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(RgbWorkingSpaceBase workingSpace)
{
if (this.linearRgbToCieXyzConverter?.SourceWorkingSpace.Equals(workingSpace) == true)
{

2
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs

@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
private readonly CieXyz targetLuvWhitePoint;
private readonly CieXyz targetLabWhitePoint;
private readonly CieXyz targetHunterLabWhitePoint;
private readonly RgbWorkingSpace targetRgbWorkingSpace;
private readonly RgbWorkingSpaceBase targetRgbWorkingSpace;
private readonly IChromaticAdaptation chromaticAdaptation;
private readonly bool performChromaticAdaptation;
private readonly CieXyzAndLmsConverter cieXyzAndLmsConverter;

2
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs

@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// Gets or sets the target working space used *when creating* RGB colors. (RGB colors on the input already contain the working space information)
/// Defaults to: <see cref="Rgb.DefaultWorkingSpace"/>.
/// </summary>
public RgbWorkingSpace TargetRgbWorkingSpace { get; set; } = Rgb.DefaultWorkingSpace;
public RgbWorkingSpaceBase TargetRgbWorkingSpace { get; set; } = Rgb.DefaultWorkingSpace;
/// <summary>
/// Gets or sets the chromatic adaptation method used. When <value>null</value>, no adaptation will be performed.

35
src/ImageSharp/ColorSpaces/Conversion/ICompanding.cs

@ -1,35 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Pair of companding functions for <see cref="RgbWorkingSpace"/>.
/// Used for conversion to <see cref="CieXyz"/> and backwards.
/// See also: <seealso cref="RgbWorkingSpace.Companding"/>
/// </summary>
public interface ICompanding
{
/// <summary>
/// Expands a companded channel to its linear equivalent with respect to the energy.
/// </summary>
/// <remarks>
/// For more info see:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
/// </remarks>
/// <param name="channel">The channel value</param>
/// <returns>The linear channel value</returns>
float Expand(float channel);
/// <summary>
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent (depends on the RGB color system).
/// </summary>
/// <remarks>
/// For more info see:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
/// <param name="channel">The channel value</param>
/// <returns>The nonlinear channel value</returns>
float Compress(float channel);
}
}

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CIeLchToCieLabConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLabToCieLchConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLabToCieXyzConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLchuvToCieLuvConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuvToCieLchuvConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuvToCieXyzConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndCieXyyConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndHunterLabConverterBase.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndHunterLabConverterBase.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzToCieLabConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzToCieLuvConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLuvConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzToHunterLabConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToHunterLabConverter.cs

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzToLinearRgbConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs

@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// Initializes a new instance of the <see cref="CieXyzToLinearRgbConverter"/> class.
/// </summary>
/// <param name="workingSpace">The target working space.</param>
public CieXyzToLinearRgbConverter(RgbWorkingSpace workingSpace)
public CieXyzToLinearRgbConverter(RgbWorkingSpaceBase workingSpace)
{
this.TargetWorkingSpace = workingSpace;
this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace);
@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// <summary>
/// Gets the target working space
/// </summary>
public RgbWorkingSpace TargetWorkingSpace { get; }
public RgbWorkingSpaceBase TargetWorkingSpace { get; }
/// <summary>
/// Performs the conversion from the <see cref="CieXyz"/> input to an instance of <see cref="LinearRgb"/> type.

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/CmykAndRgbConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/HslAndRgbConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/HsvAndRgbConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLabToCieXyzConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/LinearRgbAndCieXyzConverterBase.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs

@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// </summary>
/// <param name="workingSpace">The Rgb working space.</param>
/// <returns>The <see cref="Matrix4x4"/> based on the chromaticity and working space.</returns>
public static Matrix4x4 GetRgbToCieXyzMatrix(RgbWorkingSpace workingSpace)
public static Matrix4x4 GetRgbToCieXyzMatrix(RgbWorkingSpaceBase workingSpace)
{
DebugGuard.NotNull(workingSpace, nameof(workingSpace));
RgbPrimariesChromaticityCoordinates chromaticity = workingSpace.ChromaticityCoordinates;

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/LinearRgbToCieXyzConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs

@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// Initializes a new instance of the <see cref="LinearRgbToCieXyzConverter"/> class.
/// </summary>
/// <param name="workingSpace">The target working space.</param>
public LinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace)
public LinearRgbToCieXyzConverter(RgbWorkingSpaceBase workingSpace)
{
this.SourceWorkingSpace = workingSpace;
this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace);
@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// <summary>
/// Gets the source working space
/// </summary>
public RgbWorkingSpace SourceWorkingSpace { get; }
public RgbWorkingSpaceBase SourceWorkingSpace { get; }
/// <summary>
/// Performs the conversion from the <see cref="LinearRgb"/> input to an instance of <see cref="CieXyz"/> type.

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/LinearRgbToRgbConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs

@ -19,9 +19,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
public Rgb Convert(in LinearRgb input)
{
var vector = input.ToVector3();
vector.X = input.WorkingSpace.Companding.Compress(vector.X);
vector.Y = input.WorkingSpace.Companding.Compress(vector.Y);
vector.Z = input.WorkingSpace.Companding.Compress(vector.Z);
vector.X = input.WorkingSpace.Compress(vector.X);
vector.Y = input.WorkingSpace.Compress(vector.Y);
vector.Z = input.WorkingSpace.Compress(vector.Z);
return new Rgb(vector, input.WorkingSpace);
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbToLinearRgbConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs

@ -19,9 +19,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
public LinearRgb Convert(in Rgb input)
{
var vector = input.ToVector3();
vector.X = input.WorkingSpace.Companding.Expand(vector.X);
vector.Y = input.WorkingSpace.Companding.Expand(vector.Y);
vector.Z = input.WorkingSpace.Companding.Expand(vector.Z);
vector.X = input.WorkingSpace.Expand(vector.X);
vector.Y = input.WorkingSpace.Expand(vector.Y);
vector.Z = input.WorkingSpace.Expand(vector.Z);
return new LinearRgb(vector, input.WorkingSpace);
}

0
src/ImageSharp/ColorSpaces/Conversion/Implementation/YCbCrAndRgbConverter.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs

37
src/ImageSharp/ColorSpaces/Conversion/Implementation/GammaCompanding.cs

@ -1,37 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Implements gamma companding
/// </summary>
/// <remarks>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
public sealed class GammaCompanding : ICompanding
{
/// <summary>
/// Initializes a new instance of the <see cref="GammaCompanding"/> class.
/// </summary>
/// <param name="gamma">The gamma value.</param>
public GammaCompanding(float gamma) => this.Gamma = gamma;
/// <summary>
/// Gets the gamma value
/// </summary>
public float Gamma { get; }
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public float Expand(float channel) => MathF.Pow(channel, this.Gamma);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public float Compress(float channel) => MathF.Pow(channel, 1 / this.Gamma);
}
}

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

@ -1,33 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Implements L* companding
/// </summary>
/// <remarks>
/// For more info see:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
public sealed class LCompanding : ICompanding
{
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public float Expand(float channel)
=> channel <= 0.08 ? 100 * channel / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public float Compress(float channel)
{
return channel <= CieConstants.Epsilon
? channel * CieConstants.Kappa / 100F
: MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F;
}
}
}

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs

@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Represents the chromaticity coordinates of RGB primaries.
/// One of the specifiers of <see cref="RgbWorkingSpace"/>.
/// One of the specifiers of <see cref="RgbWorkingSpaceBase"/>.
/// </summary>
public readonly struct RgbPrimariesChromaticityCoordinates : IEquatable<RgbPrimariesChromaticityCoordinates>
{

27
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rec709Companding.cs

@ -1,27 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Implements the Rec. 709 companding function
/// </summary>
/// <remarks>
/// http://en.wikipedia.org/wiki/Rec._709
/// </remarks>
public sealed class Rec709Companding : ICompanding
{
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public float Expand(float channel)
=> channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public float Compress(float channel)
=> channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F;
}
}

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

@ -1,90 +0,0 @@
// 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>
public class RgbWorkingSpace : IEquatable<RgbWorkingSpace>
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbWorkingSpace"/> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="companding">The function pair for converting to <see cref="CieXyz"/> and back.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public RgbWorkingSpace(CieXyz referenceWhite, ICompanding companding, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
{
this.WhitePoint = referenceWhite;
this.Companding = companding;
this.ChromaticityCoordinates = chromaticityCoordinates;
}
/// <summary>
/// Gets the reference white point
/// </summary>
public CieXyz WhitePoint { get; }
/// <summary>
/// Gets the function pair for converting to <see cref="CieXyz"/> and back.
/// </summary>
public ICompanding Companding { get; }
/// <summary>
/// Gets the chromaticity of the rgb primaries.
/// </summary>
public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <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>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator ==(RgbWorkingSpace left, RgbWorkingSpace right)
{
return Equals(left, right);
}
/// <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>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
public static bool operator !=(RgbWorkingSpace left, RgbWorkingSpace right)
{
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)
{
// Object.Equals for ICompanding compares the reference only.
return this.WhitePoint.Equals(other.WhitePoint)
&& this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates)
&& Equals(this.Companding, other.Companding);
}
/// <inheritdoc/>
public override int GetHashCode()
{
int hash = this.WhitePoint.GetHashCode();
hash = HashHelpers.Combine(hash, this.ChromaticityCoordinates.GetHashCode());
return HashHelpers.Combine(hash, this.Companding?.GetHashCode() ?? 0);
}
}
}

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

@ -1,33 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Implements sRGB companding
/// </summary>
/// <remarks>
/// For more info see:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
public sealed class SRgbCompanding : ICompanding
{
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F;
}
}
}

36
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaCompanding.cs

@ -0,0 +1,36 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Implements gamma companding
/// </summary>
/// <remarks>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
public static class GammaCompanding
{
/// <summary>
/// Expands a companded channel to its linear equivalent with respect to the energy.
/// </summary>
/// <param name="channel">The channel value.</param>
/// <param name="gamma">The gamma value.</param>
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Expand(float channel, float gamma) => MathF.Pow(channel, gamma);
/// <summary>
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
/// </summary>
/// <param name="channel">The channel value.</param>
/// <param name="gamma">The gamma value.</param>
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Compress(float channel, float gamma) => MathF.Pow(channel, 1 / gamma);
}
}

65
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs

@ -0,0 +1,65 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// The gamma working space.
/// </summary>
public class GammaWorkingSpace : RgbWorkingSpaceBase
{
/// <summary>
/// Initializes a new instance of the <see cref="GammaWorkingSpace" /> class.
/// </summary>
/// <param name="gamma">The gamma value.</param>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public GammaWorkingSpace(float gamma, CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
: base(referenceWhite, chromaticityCoordinates) => this.Gamma = gamma;
/// <summary>
/// Gets the gamma value.
/// </summary>
public float Gamma { get; }
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Compress(float channel) => GammaCompanding.Compress(channel, this.Gamma);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => GammaCompanding.Expand(channel, this.Gamma);
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj is GammaWorkingSpace other)
{
return this.Gamma.Equals(other.Gamma)
&& this.WhitePoint.Equals(other.WhitePoint)
&& this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates);
}
return false;
}
/// <inheritdoc/>
public override int GetHashCode()
{
int hash = base.GetHashCode();
return HashHelpers.Combine(hash, this.Gamma.GetHashCode());
}
}
}

37
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LCompanding.cs

@ -0,0 +1,37 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Implements L* companding
/// </summary>
/// <remarks>
/// For more info see:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
public static class LCompanding
{
/// <summary>
/// Expands a companded channel to its linear equivalent with respect to the energy.
/// </summary>
/// <param name="channel">The channel value.</param>
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Expand(float channel)
=> channel <= 0.08 ? 100 * channel / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F);
/// <summary>
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
/// </summary>
/// <param name="channel">The channel value</param>
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Compress(float channel)
=> channel <= CieConstants.Epsilon ? channel * CieConstants.Kappa / 100F : MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F;
}
}

31
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs

@ -0,0 +1,31 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// L* working space.
/// </summary>
public sealed class LWorkingSpace : RgbWorkingSpaceBase
{
/// <summary>
/// Initializes a new instance of the <see cref="LWorkingSpace" /> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public LWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
: base(referenceWhite, chromaticityCoordinates)
{
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Compress(float channel) => LCompanding.Compress(channel);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => LCompanding.Expand(channel);
}
}

18
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rec2020Companding.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020Companding.cs

@ -13,16 +13,24 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// <see href="http://en.wikipedia.org/wiki/Rec._2020"/>
/// For 10-bits, companding is identical to <see cref="Rec709Companding"/>
/// </remarks>
public sealed class Rec2020Companding : ICompanding
public static class Rec2020Companding
{
/// <inheritdoc/>
/// <summary>
/// Expands a companded channel to its linear equivalent with respect to the energy.
/// </summary>
/// <param name="channel">The channel value.</param>
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public float Expand(float channel)
public static float Expand(float channel)
=> channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F);
/// <inheritdoc/>
/// <summary>
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
/// </summary>
/// <param name="channel">The channel value.</param>
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public float Compress(float channel)
public static float Compress(float channel)
=> channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F;
}
}

31
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs

@ -0,0 +1,31 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Rec. 2020 (ITU-R Recommendation BT.2020F) working space.
/// </summary>
public sealed class Rec2020WorkingSpace : RgbWorkingSpaceBase
{
/// <summary>
/// Initializes a new instance of the <see cref="Rec2020WorkingSpace" /> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public Rec2020WorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
: base(referenceWhite, chromaticityCoordinates)
{
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Compress(float channel) => Rec2020Companding.Compress(channel);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => Rec2020Companding.Expand(channel);
}
}

35
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709Companding.cs

@ -0,0 +1,35 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Implements the Rec. 709 companding function.
/// </summary>
/// <remarks>
/// http://en.wikipedia.org/wiki/Rec._709
/// </remarks>
public static class Rec709Companding
{
/// <summary>
/// Expands a companded channel to its linear equivalent with respect to the energy.
/// </summary>
/// <param name="channel">The channel value.</param>
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Expand(float channel)
=> channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F);
/// <summary>
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
/// </summary>
/// <param name="channel">The channel value.</param>
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Compress(float channel)
=> channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F;
}
}

31
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs

@ -0,0 +1,31 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Rec. 709 (ITU-R Recommendation BT.709) working space.
/// </summary>
public sealed class Rec709WorkingSpace : RgbWorkingSpaceBase
{
/// <summary>
/// Initializes a new instance of the <see cref="Rec709WorkingSpace" /> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public Rec709WorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
: base(referenceWhite, chromaticityCoordinates)
{
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Compress(float channel) => Rec709Companding.Compress(channel);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => Rec709Companding.Expand(channel);
}
}

83
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs

@ -0,0 +1,83 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Base class for all implementations of <see cref="RgbWorkingSpaceBase"/>.
/// </summary>
public abstract class RgbWorkingSpaceBase
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbWorkingSpaceBase"/> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
protected RgbWorkingSpaceBase(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
{
this.WhitePoint = referenceWhite;
this.ChromaticityCoordinates = chromaticityCoordinates;
}
/// <summary>
/// Gets the reference white point
/// </summary>
public CieXyz WhitePoint { get; }
/// <summary>
/// Gets the chromaticity of the rgb primaries.
/// </summary>
public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <summary>
/// Expands a companded channel to its linear equivalent with respect to the energy.
/// </summary>
/// <remarks>
/// For more info see:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
/// </remarks>
/// <param name="channel">The channel value.</param>
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
public abstract float Expand(float channel);
/// <summary>
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent (depends on the RGB color system).
/// </summary>
/// <remarks>
/// For more info see:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
/// <param name="channel">The channel value.</param>
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
public abstract float Compress(float channel);
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj is RgbWorkingSpaceBase other)
{
return this.WhitePoint.Equals(other.WhitePoint)
&& this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates);
}
return false;
}
/// <inheritdoc/>
public override int GetHashCode()
{
int hash = this.WhitePoint.GetHashCode();
return HashHelpers.Combine(hash, this.ChromaticityCoordinates.GetHashCode());
}
}
}

35
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbCompanding.cs

@ -0,0 +1,35 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// Implements sRGB companding
/// </summary>
/// <remarks>
/// For more info see:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
public static class SRgbCompanding
{
/// <summary>
/// Expands a companded channel to its linear equivalent with respect to the energy.
/// </summary>
/// <param name="channel">The channel value</param>
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Expand(float channel) => channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F);
/// <summary>
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
/// </summary>
/// <param name="channel">The channel value</param>
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Compress(float channel) => channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F;
}
}

31
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs

@ -0,0 +1,31 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
/// <summary>
/// The sRgb working space.
/// </summary>
public sealed class SRgbWorkingSpace : RgbWorkingSpaceBase
{
/// <summary>
/// Initializes a new instance of the <see cref="SRgbWorkingSpace" /> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public SRgbWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
: base(referenceWhite, chromaticityCoordinates)
{
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Compress(float channel) => SRgbCompanding.Compress(channel);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => SRgbCompanding.Expand(channel);
}
}

10
src/ImageSharp/ColorSpaces/LinearRgb.cs

@ -9,7 +9,7 @@ using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces
{
/// <summary>
/// Represents an linear Rgb color with specified <see cref="RgbWorkingSpace"/> working space
/// Represents an linear Rgb color with specified <see cref="RgbWorkingSpaceBase"/> working space
/// </summary>
public readonly struct LinearRgb : IEquatable<LinearRgb>
{
@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// The default LinearRgb working space.
/// </summary>
public static readonly RgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
public static readonly RgbWorkingSpaceBase DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
/// <summary>
/// Gets the red component.
@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// Gets the LinearRgb color space <seealso cref="RgbWorkingSpaces"/>
/// </summary>
public readonly RgbWorkingSpace WorkingSpace;
public readonly RgbWorkingSpaceBase WorkingSpace;
/// <summary>
/// Initializes a new instance of the <see cref="LinearRgb"/> struct.
@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <param name="b">The blue component ranging between 0 and 1.</param>
/// <param name="workingSpace">The rgb working space.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public LinearRgb(float r, float g, float b, RgbWorkingSpace workingSpace)
public LinearRgb(float r, float g, float b, RgbWorkingSpaceBase workingSpace)
: this(new Vector3(r, g, b), workingSpace)
{
}
@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <param name="vector">The vector representing the r, g, b components.</param>
/// <param name="workingSpace">The LinearRgb working space.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public LinearRgb(Vector3 vector, RgbWorkingSpace workingSpace)
public LinearRgb(Vector3 vector, RgbWorkingSpaceBase workingSpace)
{
// Clamp to 0-1 range.
vector = Vector3.Clamp(vector, Min, Max);

10
src/ImageSharp/ColorSpaces/Rgb.cs

@ -10,7 +10,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.ColorSpaces
{
/// <summary>
/// Represents an RGB color with specified <see cref="RgbWorkingSpace"/> working space.
/// Represents an RGB color with specified <see cref="RgbWorkingSpaceBase"/> working space.
/// </summary>
public readonly struct Rgb : IEquatable<Rgb>
{
@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// The default rgb working space
/// </summary>
public static readonly RgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
public static readonly RgbWorkingSpaceBase DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
/// <summary>
/// Gets the red component.
@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <summary>
/// Gets the Rgb color space <seealso cref="RgbWorkingSpaces"/>
/// </summary>
public readonly RgbWorkingSpace WorkingSpace;
public readonly RgbWorkingSpaceBase WorkingSpace;
/// <summary>
/// Initializes a new instance of the <see cref="Rgb"/> struct.
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <param name="b">The blue component ranging between 0 and 1.</param>
/// <param name="workingSpace">The rgb working space.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb(float r, float g, float b, RgbWorkingSpace workingSpace)
public Rgb(float r, float g, float b, RgbWorkingSpaceBase workingSpace)
: this(new Vector3(r, g, b), workingSpace)
{
}
@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <param name="vector">The vector representing the r, g, b components.</param>
/// <param name="workingSpace">The rgb working space.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb(Vector3 vector, RgbWorkingSpace workingSpace)
public Rgb(Vector3 vector, RgbWorkingSpaceBase workingSpace)
{
vector = Vector3.Clamp(vector, Min, Max);
this.R = vector.X;

38
src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs

@ -19,97 +19,97 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Uses proper companding function, according to:
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_Rgb_to_XYZ.html"/>
/// </remarks>
public static readonly RgbWorkingSpace SRgb = new RgbWorkingSpace(Illuminants.D65, new SRgbCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
public static readonly RgbWorkingSpaceBase SRgb = new SRgbWorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
/// <summary>
/// Simplified sRgb working space (uses <see cref="GammaCompanding">gamma companding</see> instead of <see cref="SRgbCompanding"/>).
/// See also <see cref="SRgb"/>.
/// </summary>
public static readonly RgbWorkingSpace SRgbSimplified = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
public static readonly RgbWorkingSpaceBase SRgbSimplified = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.3000F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
/// <summary>
/// Rec. 709 (ITU-R Recommendation BT.709) working space.
/// </summary>
public static readonly RgbWorkingSpace Rec709 = new RgbWorkingSpace(Illuminants.D65, new Rec709Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F)));
public static readonly RgbWorkingSpaceBase Rec709 = new Rec709WorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.64F, 0.33F), new CieXyChromaticityCoordinates(0.30F, 0.60F), new CieXyChromaticityCoordinates(0.15F, 0.06F)));
/// <summary>
/// Rec. 2020 (ITU-R Recommendation BT.2020F) working space.
/// </summary>
public static readonly RgbWorkingSpace Rec2020 = new RgbWorkingSpace(Illuminants.D65, new Rec2020Companding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F)));
public static readonly RgbWorkingSpaceBase Rec2020 = new Rec2020WorkingSpace(Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.708F, 0.292F), new CieXyChromaticityCoordinates(0.170F, 0.797F), new CieXyChromaticityCoordinates(0.131F, 0.046F)));
/// <summary>
/// ECI Rgb v2 working space.
/// </summary>
public static readonly RgbWorkingSpace ECIRgbv2 = new RgbWorkingSpace(Illuminants.D50, new LCompanding(), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F)));
public static readonly RgbWorkingSpaceBase ECIRgbv2 = new LWorkingSpace(Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F)));
/// <summary>
/// Adobe Rgb (1998) working space.
/// </summary>
public static readonly RgbWorkingSpace AdobeRgb1998 = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
public static readonly RgbWorkingSpaceBase AdobeRgb1998 = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
/// <summary>
/// Apple sRgb working space.
/// </summary>
public static readonly RgbWorkingSpace ApplesRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F)));
public static readonly RgbWorkingSpaceBase ApplesRgb = new GammaWorkingSpace(1.8F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6250F, 0.3400F), new CieXyChromaticityCoordinates(0.2800F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F)));
/// <summary>
/// Best Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace BestRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F)));
public static readonly RgbWorkingSpaceBase BestRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.2150F, 0.7750F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F)));
/// <summary>
/// Beta Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace BetaRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F)));
public static readonly RgbWorkingSpaceBase BetaRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6888F, 0.3112F), new CieXyChromaticityCoordinates(0.1986F, 0.7551F), new CieXyChromaticityCoordinates(0.1265F, 0.0352F)));
/// <summary>
/// Bruce Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace BruceRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
public static readonly RgbWorkingSpaceBase BruceRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2800F, 0.6500F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
/// <summary>
/// CIE Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace CIERgb = new RgbWorkingSpace(Illuminants.E, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F)));
public static readonly RgbWorkingSpaceBase CIERgb = new GammaWorkingSpace(2.2F, Illuminants.E, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.2740F, 0.7170F), new CieXyChromaticityCoordinates(0.1670F, 0.0090F)));
/// <summary>
/// ColorMatch Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace ColorMatchRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F)));
public static readonly RgbWorkingSpaceBase ColorMatchRgb = new GammaWorkingSpace(1.8F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.2950F, 0.6050F), new CieXyChromaticityCoordinates(0.1500F, 0.0750F)));
/// <summary>
/// Don Rgb 4 working space.
/// </summary>
public static readonly RgbWorkingSpace DonRgb4 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F)));
public static readonly RgbWorkingSpaceBase DonRgb4 = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6960F, 0.3000F), new CieXyChromaticityCoordinates(0.2150F, 0.7650F), new CieXyChromaticityCoordinates(0.1300F, 0.0350F)));
/// <summary>
/// Ekta Space PS5 working space.
/// </summary>
public static readonly RgbWorkingSpace EktaSpacePS5 = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F)));
public static readonly RgbWorkingSpaceBase EktaSpacePS5 = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6950F, 0.3050F), new CieXyChromaticityCoordinates(0.2600F, 0.7000F), new CieXyChromaticityCoordinates(0.1100F, 0.0050F)));
/// <summary>
/// NTSC Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace NTSCRgb = new RgbWorkingSpace(Illuminants.C, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F)));
public static readonly RgbWorkingSpaceBase NTSCRgb = new GammaWorkingSpace(2.2F, Illuminants.C, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6700F, 0.3300F), new CieXyChromaticityCoordinates(0.2100F, 0.7100F), new CieXyChromaticityCoordinates(0.1400F, 0.0800F)));
/// <summary>
/// PAL/SECAM Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace PALSECAMRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
public static readonly RgbWorkingSpaceBase PALSECAMRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6400F, 0.3300F), new CieXyChromaticityCoordinates(0.2900F, 0.6000F), new CieXyChromaticityCoordinates(0.1500F, 0.0600F)));
/// <summary>
/// ProPhoto Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace ProPhotoRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(1.8F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F)));
public static readonly RgbWorkingSpaceBase ProPhotoRgb = new GammaWorkingSpace(1.8F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7347F, 0.2653F), new CieXyChromaticityCoordinates(0.1596F, 0.8404F), new CieXyChromaticityCoordinates(0.0366F, 0.0001F)));
/// <summary>
/// SMPTE-C Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace SMPTECRgb = new RgbWorkingSpace(Illuminants.D65, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F)));
public static readonly RgbWorkingSpaceBase SMPTECRgb = new GammaWorkingSpace(2.2F, Illuminants.D65, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.6300F, 0.3400F), new CieXyChromaticityCoordinates(0.3100F, 0.5950F), new CieXyChromaticityCoordinates(0.1550F, 0.0700F)));
/// <summary>
/// Wide Gamut Rgb working space.
/// </summary>
public static readonly RgbWorkingSpace WideGamutRgb = new RgbWorkingSpace(Illuminants.D50, new GammaCompanding(2.2F), new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F)));
public static readonly RgbWorkingSpaceBase WideGamutRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F)));
}
}

21
tests/ImageSharp.Tests/Colorspaces/Conversion/ApproximateColorspaceComparer.cs

@ -27,7 +27,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
IEqualityComparer<YCbCr>,
IEqualityComparer<CieXyChromaticityCoordinates>,
IEqualityComparer<RgbPrimariesChromaticityCoordinates>,
IEqualityComparer<RgbWorkingSpace>
IEqualityComparer<GammaWorkingSpace>,
IEqualityComparer<RgbWorkingSpaceBase>
{
private readonly float Epsilon;
@ -205,20 +206,30 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
public int GetHashCode(RgbPrimariesChromaticityCoordinates obj) => obj.GetHashCode();
/// <inheritdoc/>
public bool Equals(RgbWorkingSpace x, RgbWorkingSpace y)
public bool Equals(GammaWorkingSpace x, GammaWorkingSpace y)
{
if (x is RgbWorkingSpace g1 && y is RgbWorkingSpace g2)
if (x is GammaWorkingSpace g1 && y is GammaWorkingSpace g2)
{
return this.Equals(g1.WhitePoint, g2.WhitePoint)
return this.Equals(g1.Gamma, g2.Gamma)
&& this.Equals(g1.WhitePoint, g2.WhitePoint)
&& this.Equals(g1.ChromaticityCoordinates, g2.ChromaticityCoordinates);
}
return false;
}
/// <inheritdoc/>
public int GetHashCode(GammaWorkingSpace obj) => obj.GetHashCode();
/// <inheritdoc/>
public bool Equals(RgbWorkingSpaceBase x, RgbWorkingSpaceBase y)
{
return this.Equals(x.WhitePoint, y.WhitePoint)
&& this.Equals(x.ChromaticityCoordinates, y.ChromaticityCoordinates);
}
/// <inheritdoc/>
public int GetHashCode(RgbWorkingSpace obj) => obj.GetHashCode();
public int GetHashCode(RgbWorkingSpaceBase obj) => obj.GetHashCode();
private bool Equals(float x, float y)
{

31
tests/ImageSharp.Tests/Colorspaces/Conversion/CompandingTests.cs

@ -18,38 +18,51 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion
[Fact]
public void Rec2020CompandingIsCorrect()
{
CompandingIsCorrectImpl(new Rec2020Companding(), .667F, .4484759F, .3937096F);
const float input = .667F;
float e = Rec2020Companding.Expand(input);
float c = Rec2020Companding.Compress(e);
CompandingIsCorrectImpl(e, c, .4484759F, .3937096F);
}
[Fact]
public void Rec709CompandingIsCorrect()
{
CompandingIsCorrectImpl(new Rec709Companding(), .667F, .4483577F, .3937451F);
const float input = .667F;
float e = Rec709Companding.Expand(input);
float c = Rec709Companding.Compress(e);
CompandingIsCorrectImpl(e, c, .4483577F, .3937451F);
}
[Fact]
public void SRgbCompandingIsCorrect()
{
CompandingIsCorrectImpl(new SRgbCompanding(), .667F, .40242353F, .667F);
const float input = .667F;
float e = SRgbCompanding.Expand(input);
float c = SRgbCompanding.Compress(e);
CompandingIsCorrectImpl(e, c, .40242353F, .667F);
}
[Fact]
public void GammaCompandingIsCorrect()
{
CompandingIsCorrectImpl(new GammaCompanding(2.2F), .667F, .41027668F, .667F);
const float gamma = 2.2F;
const float input = .667F;
float e = GammaCompanding.Expand(input, gamma);
float c = GammaCompanding.Compress(e, gamma);
CompandingIsCorrectImpl(e, c, .41027668F, .667F);
}
[Fact]
public void LCompandingIsCorrect()
{
CompandingIsCorrectImpl(new LCompanding(), .667F, .36236193F, .58908917F);
const float input = .667F;
float e = LCompanding.Expand(input);
float c = LCompanding.Compress(e);
CompandingIsCorrectImpl(e, c, .36236193F, .58908917F);
}
private static void CompandingIsCorrectImpl(ICompanding companding, float input, float expanded, float compressed)
private static void CompandingIsCorrectImpl(float e, float c, float expanded, float compressed)
{
float e = companding.Expand(input);
float c = companding.Compress(e);
Assert.Equal(expanded, e, FloatComparer);
Assert.Equal(compressed, c, FloatComparer);
}

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

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.Numerics;
@ -20,11 +19,9 @@ namespace SixLabors.ImageSharp.Tests
/// 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.Epsilon = epsilon;
}
public ApproximateFloatComparer(float epsilon = 1f) => this.Epsilon = epsilon;
/// <inheritdoc/>
public bool Equals(float x, float y)
{
float d = x - y;
@ -32,19 +29,13 @@ namespace SixLabors.ImageSharp.Tests
return d >= -this.Epsilon && d <= this.Epsilon;
}
public int GetHashCode(float obj)
{
return obj.GetHashCode();
}
/// <inheritdoc/>
public int GetHashCode(float obj) => obj.GetHashCode();
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 bool Equals(Vector4 x, Vector4 y) => this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y) && this.Equals(x.Z, y.Z) && this.Equals(x.W, y.W);
public int GetHashCode(Vector4 obj)
{
return obj.GetHashCode();
}
/// <inheritdoc/>
public int GetHashCode(Vector4 obj) => obj.GetHashCode();
}
}
Loading…
Cancel
Save