Browse Source

Refactor RgbWorkingSpace

af/merge-core
James Jackson-South 8 years ago
parent
commit
a92d8bdf76
  1. 46
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs
  2. 35
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs
  3. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs
  4. 32
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs
  5. 31
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs
  6. 89
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs
  7. 82
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs
  8. 79
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs
  9. 78
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs
  10. 80
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs
  11. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs
  12. 105
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
  13. 33
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/SRgbCompanding.cs
  14. 35
      src/ImageSharp/ColorSpaces/ICompanding.cs
  15. 21
      src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs
  16. 169
      src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs

46
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/GammaCompanding.cs

@ -1,46 +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.RgbColorSapce
{
/// <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 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(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return MathF.Pow(channel, this.Gamma);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return MathF.Pow(channel, 1 / this.Gamma);
}
}
}

35
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LCompanding.cs

@ -1,35 +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.RgbColorSapce
{
/// <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 class LCompanding : ICompanding
{
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : MathF.Pow((channel + 0.16F) / 1.16F, 3);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel <= CieConstants.Epsilon
? channel * CieConstants.Kappa / 100F
: MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F;
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToRgbConverter.cs

@ -16,9 +16,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
DebugGuard.NotNull(input, nameof(input));
Vector3 vector = input.Vector;
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);
}

32
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec2020Companding.cs

@ -1,32 +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.RgbColorSapce
{
/// <summary>
/// Implements Rec. 2020 companding function (for 12-bits).
/// </summary>
/// <remarks>
/// <see href="http://en.wikipedia.org/wiki/Rec._2020"/>
/// For 10-bits, companding is identical to <see cref="Rec709Companding"/>
/// </remarks>
public class Rec2020Companding : ICompanding
{
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F;
}
}
}

31
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/Rec709Companding.cs

@ -1,31 +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.RgbColorSapce
{
/// <summary>
/// Implements the Rec. 709 companding function
/// </summary>
/// <remarks>
/// http://en.wikipedia.org/wiki/Rec._709
/// </remarks>
public class Rec709Companding : ICompanding
{
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F;
}
}
}

89
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbGammaWorkingSpace.cs

@ -0,0 +1,89 @@
// 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.RgbColorSapce
{
/// <summary>
/// Represents an <see cref="IRgbWorkingSpace"/> that 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>
internal class RgbGammaWorkingSpace : IRgbWorkingSpace, IEquatable<RgbGammaWorkingSpace>
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbGammaWorkingSpace"/> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="gamma">The gamma value.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public RgbGammaWorkingSpace(CieXyz referenceWhite, float gamma, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
{
this.WhitePoint = referenceWhite;
this.Gamma = gamma;
this.ChromaticityCoordinates = chromaticityCoordinates;
}
/// <inheritdoc/>
public CieXyz WhitePoint { get; }
/// <inheritdoc/>
public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <summary>
/// Gets the gamma value
/// </summary>
public float Gamma { get; }
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return MathF.Pow(channel, this.Gamma);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return MathF.Pow(channel, 1 / this.Gamma);
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is RgbGammaWorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(IRgbWorkingSpace other)
{
return other is RgbGammaWorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(RgbGammaWorkingSpace other)
{
return other != null &&
this.WhitePoint.Equals(other.WhitePoint) &&
this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates) &&
this.Gamma == other.Gamma;
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashHelpers.Combine(
this.WhitePoint.GetHashCode(),
HashHelpers.Combine(
this.ChromaticityCoordinates.GetHashCode(),
this.Gamma.GetHashCode()));
}
}
}

82
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbLWorkingSpace.cs

@ -0,0 +1,82 @@
// 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.RgbColorSapce
{
/// <summary>
/// Represents an <see cref="IRgbWorkingSpace"/> that 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>
internal class RgbLWorkingSpace : IRgbWorkingSpace, IEquatable<RgbLWorkingSpace>
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbLWorkingSpace"/> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public RgbLWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
{
this.WhitePoint = referenceWhite;
this.ChromaticityCoordinates = chromaticityCoordinates;
}
/// <inheritdoc/>
public CieXyz WhitePoint { get; }
/// <inheritdoc/>
public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : MathF.Pow((channel + 0.16F) / 1.16F, 3);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel <= CieConstants.Epsilon
? channel * CieConstants.Kappa / 100F
: MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is RgbLWorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(IRgbWorkingSpace other)
{
return other is RgbLWorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(RgbLWorkingSpace other)
{
return other != null &&
this.WhitePoint.Equals(other.WhitePoint) &&
this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashHelpers.Combine(
this.WhitePoint.GetHashCode(),
this.ChromaticityCoordinates.GetHashCode());
}
}
}

79
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec2020WorkingSpace.cs

@ -0,0 +1,79 @@
// 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.RgbColorSapce
{
/// <summary>
/// Represents an <see cref="IRgbWorkingSpace"/> that implements Rec. 2020 companding (for 12-bits).
/// </summary>
/// <remarks>
/// <see href="http://en.wikipedia.org/wiki/Rec._2020"/>
/// For 10-bits, companding is identical to <see cref="RgbRec709WorkingSpace"/>
/// </remarks>
internal class RgbRec2020WorkingSpace : IRgbWorkingSpace, IEquatable<RgbRec2020WorkingSpace>
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbRec2020WorkingSpace"/> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public RgbRec2020WorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
{
this.WhitePoint = referenceWhite;
this.ChromaticityCoordinates = chromaticityCoordinates;
}
/// <inheritdoc/>
public CieXyz WhitePoint { get; }
/// <inheritdoc/>
public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is RgbRec2020WorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(IRgbWorkingSpace other)
{
return other is RgbRec2020WorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(RgbRec2020WorkingSpace other)
{
return other != null &&
this.WhitePoint.Equals(other.WhitePoint) &&
this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashHelpers.Combine(
this.WhitePoint.GetHashCode(),
this.ChromaticityCoordinates.GetHashCode());
}
}
}

78
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbRec709WorkingSpace.cs

@ -0,0 +1,78 @@
// 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.RgbColorSapce
{
/// <summary>
/// Represents an <see cref="IRgbWorkingSpace"/> that implements Rec. 709 companding.
/// </summary>
/// <remarks>
/// <see href="http://en.wikipedia.org/wiki/Rec._709"/>
/// </remarks>
internal class RgbRec709WorkingSpace : IRgbWorkingSpace, IEquatable<RgbRec709WorkingSpace>
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbRec709WorkingSpace"/> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public RgbRec709WorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
{
this.WhitePoint = referenceWhite;
this.ChromaticityCoordinates = chromaticityCoordinates;
}
/// <inheritdoc/>
public CieXyz WhitePoint { get; }
/// <inheritdoc/>
public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is RgbRec709WorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(IRgbWorkingSpace other)
{
return other is RgbRec709WorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(RgbRec709WorkingSpace other)
{
return other != null &&
this.WhitePoint.Equals(other.WhitePoint) &&
this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashHelpers.Combine(
this.WhitePoint.GetHashCode(),
this.ChromaticityCoordinates.GetHashCode());
}
}
}

80
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbSRgbWorkingSpace.cs

@ -0,0 +1,80 @@
// 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.RgbColorSapce
{
/// <summary>
/// Represents an <see cref="IRgbWorkingSpace"/> that 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>
internal class RgbSRgbWorkingSpace : IRgbWorkingSpace, IEquatable<RgbSRgbWorkingSpace>
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbSRgbWorkingSpace"/> class.
/// </summary>
/// <param name="referenceWhite">The reference white point.</param>
/// <param name="chromaticityCoordinates">The chromaticity of the rgb primaries.</param>
public RgbSRgbWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordinates chromaticityCoordinates)
{
this.WhitePoint = referenceWhite;
this.ChromaticityCoordinates = chromaticityCoordinates;
}
/// <inheritdoc/>
public CieXyz WhitePoint { get; }
/// <inheritdoc/>
public RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <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;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is RgbSRgbWorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(IRgbWorkingSpace other)
{
return other is RgbSRgbWorkingSpace space && this.Equals(space);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(RgbSRgbWorkingSpace other)
{
return other != null &&
this.WhitePoint.Equals(other.WhitePoint) &&
this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashHelpers.Combine(
this.WhitePoint.GetHashCode(),
this.ChromaticityCoordinates.GetHashCode());
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbToLinearRgbConverter.cs

@ -16,9 +16,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
Guard.NotNull(input, nameof(input));
Vector3 vector = input.Vector;
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);
}

105
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs

@ -1,105 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce
{
/// <summary>
/// Trivial implementation of <see cref="IRgbWorkingSpace"/>
/// </summary>
internal class RgbWorkingSpace : IRgbWorkingSpace
{
/// <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 left.Equals(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 !left.Equals(right);
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is RgbWorkingSpace)
{
return this.Equals((RgbWorkingSpace)obj);
}
return false;
}
/// <inheritdoc/>
public bool Equals(IRgbWorkingSpace other)
{
// This should be refactored as separate classes with different companding implementations.
return this.WhitePoint.Equals(other.WhitePoint)
&& this.ChromaticityCoordinates.Equals(other.ChromaticityCoordinates)
&& Equals(this.Companding, other.Companding);
}
/// <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;
}
}
}
}

33
src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/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.RgbColorSapce
{
/// <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 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;
}
}
}

35
src/ImageSharp/ColorSpaces/ICompanding.cs

@ -1,35 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.ColorSpaces
{
/// <summary>
/// Pair of companding functions for <see cref="IRgbWorkingSpace"/>.
/// Used for conversion to <see cref="CieXyz"/> and backwards.
/// See also: <seealso cref="IRgbWorkingSpace.Companding"/>
/// </summary>
internal 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);
}
}

21
src/ImageSharp/ColorSpaces/IRgbWorkingSpace.cs

@ -22,10 +22,25 @@ namespace SixLabors.ImageSharp.ColorSpaces
RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <summary>
/// Gets the companding function associated with the RGB color system. Used for conversion to XYZ and backwards.
/// Expands a compressed 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"/>
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
/// </remarks>
/// <param name="channel">The channel value</param>
/// <returns>The linear channel value</returns>
float Expand(float channel);
/// <summary>
/// Compresses an expanded channel (linear) to its nonlinear equivalent (depends on the RGB color system).
/// </summary>
ICompanding Companding { get; }
/// <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);
}
}

169
src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs

@ -19,97 +19,226 @@ 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 IRgbWorkingSpace 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 IRgbWorkingSpace SRgb =
new RgbSRgbWorkingSpace(
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"/>).
/// Simplified sRgb working space that uses gamma companding instead of srgb companding.
/// See also <see cref="SRgb"/>.
/// </summary>
public static readonly IRgbWorkingSpace 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 IRgbWorkingSpace SRgbSimplified =
new RgbGammaWorkingSpace(
Illuminants.D65,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace Rec709 =
new RgbRec709WorkingSpace(
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 IRgbWorkingSpace 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 IRgbWorkingSpace Rec2020 =
new RgbRec2020WorkingSpace(
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 IRgbWorkingSpace 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 IRgbWorkingSpace ECIRgbv2 =
new RgbLWorkingSpace(
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 IRgbWorkingSpace 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 IRgbWorkingSpace AdobeRgb1998 =
new RgbGammaWorkingSpace(
Illuminants.D65,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace ApplesRgb =
new RgbGammaWorkingSpace(
Illuminants.D65,
1.8F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace BestRgb =
new RgbGammaWorkingSpace(
Illuminants.D50,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace BetaRgb =
new RgbGammaWorkingSpace(
Illuminants.D50,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace BruceRgb =
new RgbGammaWorkingSpace(
Illuminants.D65,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace CIERgb =
new RgbGammaWorkingSpace(
Illuminants.E,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace ColorMatchRgb =
new RgbGammaWorkingSpace(
Illuminants.D50,
1.8F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace DonRgb4 =
new RgbGammaWorkingSpace(
Illuminants.D50,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace EktaSpacePS5 =
new RgbGammaWorkingSpace(
Illuminants.D50,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace NTSCRgb =
new RgbGammaWorkingSpace(
Illuminants.C,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace PALSECAMRgb =
new RgbGammaWorkingSpace(
Illuminants.D65,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace ProPhotoRgb =
new RgbGammaWorkingSpace(
Illuminants.D50,
1.8F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace SMPTECRgb =
new RgbGammaWorkingSpace(
Illuminants.D65,
2.2F,
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 IRgbWorkingSpace 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 IRgbWorkingSpace WideGamutRgb =
new RgbGammaWorkingSpace(
Illuminants.D50,
2.2F,
new RgbPrimariesChromaticityCoordinates(
new CieXyChromaticityCoordinates(0.7350F, 0.2650F),
new CieXyChromaticityCoordinates(0.1150F, 0.8260F),
new CieXyChromaticityCoordinates(0.1570F, 0.0180F)));
}
}
Loading…
Cancel
Save