Browse Source

Add RGB working spaces

pull/181/head
James Jackson-South 9 years ago
parent
commit
db30cdd615
  1. 145
      src/ImageSharp/Colors/Spaces/CieXyChromaticityCoordinates.cs
  2. 2
      src/ImageSharp/Colors/Spaces/Conversion/CieConstants.cs
  3. 5
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Adapt.cs
  4. 6
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLab.cs
  5. 6
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyz.cs
  6. 5
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Lms.cs
  7. 9
      src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.cs
  8. 4
      src/ImageSharp/Colors/Spaces/Conversion/IChromaticAdaptation.cs
  9. 2
      src/ImageSharp/Colors/Spaces/Conversion/IColorConversion.cs
  10. 5
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs
  11. 5
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs
  12. 5
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs
  13. 6
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Lms/LmsAdaptationMatrix.cs
  14. 48
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/GammaCompanding.cs
  15. 37
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/LCompanding.cs
  16. 107
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs
  17. 34
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/Rec2020Companding.cs
  18. 33
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/Rec709Companding.cs
  19. 107
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
  20. 35
      src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/SRgbCompanding.cs
  21. 6
      src/ImageSharp/Colors/Spaces/Conversion/VonKriesChromaticAdaptation.cs
  22. 12
      src/ImageSharp/Colors/Spaces/ICompanding.cs
  23. 23
      src/ImageSharp/Colors/Spaces/IRgbWorkingSpace.cs
  24. 117
      src/ImageSharp/Colors/Spaces/RgbWorkingSpaces.cs
  25. 3
      tests/ImageSharp.Benchmarks/Color/ColorspaceConvert.cs
  26. 3
      tests/ImageSharp.Tests/Colors/Colorspaces/CieXyzAndCieLabConversionTest.cs
  27. 3
      tests/ImageSharp.Tests/Colors/Colorspaces/CieXyzAndLmsConversionTest.cs
  28. 9
      tests/ImageSharp.Tests/Colors/Colorspaces/ColorConverterAdaptTest.cs

145
src/ImageSharp/Colors/Spaces/CieXyChromaticityCoordinates.cs

@ -0,0 +1,145 @@
// <copyright file="CieXyChromaticityCoordinates.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces
{
using System;
using System.ComponentModel;
using System.Numerics;
/// <summary>
/// Represents the coordinates of CIEXY chromaticity space
/// </summary>
public struct CieXyChromaticityCoordinates : IEquatable<CieXyChromaticityCoordinates>, IAlmostEquatable<CieXyChromaticityCoordinates, float>
{
/// <summary>
/// Represents a <see cref="CieXyChromaticityCoordinates"/> that has X, Y values set to zero.
/// </summary>
public static readonly CieXyChromaticityCoordinates Empty = default(CieXyChromaticityCoordinates);
/// <summary>
/// The backing vector for SIMD support.
/// </summary>
private readonly Vector2 backingVector;
/// <summary>
/// Initializes a new instance of the <see cref="CieXyChromaticityCoordinates"/> struct.
/// </summary>
/// <param name="x">Chromaticity coordinate x (usually from 0 to 1)</param>
/// <param name="y">Chromaticity coordinate y (usually from 0 to 1)</param>
public CieXyChromaticityCoordinates(float x, float y)
: this(new Vector2(x, y))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CieXyChromaticityCoordinates"/> struct.
/// </summary>
/// <param name="vector">The vector containing the XY Chromaticity coordinates</param>
public CieXyChromaticityCoordinates(Vector2 vector)
{
this.backingVector = vector;
}
/// <summary>
/// Gets the chromaticity X-coordinate.
/// </summary>
/// <remarks>
/// Ranges usually from 0 to 1.
/// </remarks>
public float X => this.backingVector.X;
/// <summary>
/// Gets the chromaticity Y-coordinate
/// </summary>
/// <remarks>
/// Ranges usually from 0 to 1.
/// </remarks>
public float Y => this.backingVector.Y;
/// <summary>
/// Gets a value indicating whether this <see cref="CieXyChromaticityCoordinates"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Compares two <see cref="CieXyChromaticityCoordinates"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="CieXyChromaticityCoordinates"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="CieXyChromaticityCoordinates"/> 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 ==(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right)
{
return left.Equals(right);
}
/// <summary>
/// Compares two <see cref="CieXyChromaticityCoordinates"/> objects for inequality
/// </summary>
/// <param name="left">
/// The <see cref="CieXyChromaticityCoordinates"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="CieXyChromaticityCoordinates"/> 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 !=(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right)
{
return !left.Equals(right);
}
/// <inheritdoc />
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
}
/// <inheritdoc/>
public override string ToString()
{
if (this.IsEmpty)
{
return "CieXyChromaticityCoordinates [Empty]";
}
return $"CieXyChromaticityCoordinates [ X={this.X:#0.##}, Y={this.Y:#0.##}]";
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is CieXyChromaticityCoordinates)
{
return this.Equals((CieXyChromaticityCoordinates)obj);
}
return false;
}
/// <inheritdoc/>
public bool Equals(CieXyChromaticityCoordinates other)
{
return this.backingVector.Equals(other.backingVector);
}
/// <inheritdoc/>
public bool AlmostEquals(CieXyChromaticityCoordinates other, float precision)
{
Vector2 result = Vector2.Abs(this.backingVector - other.backingVector);
return result.X <= precision
&& result.Y <= precision;
}
}
}

2
src/ImageSharp/Colors/Spaces/Conversion/CieConstants.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
/// <summary>
/// Constants use for Cie conversion calculations

5
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Adapt.cs

@ -3,10 +3,11 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
using System;
using Spaces;
using ImageSharp.Colors.Spaces;
/// <summary>
/// Converts between color spaces ensuring that the color is adapted using chromatic adaptation.

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

@ -3,10 +3,10 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
using Implementation;
using Spaces;
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion.Implementation.CieLab;
/// <summary>
/// Converts between color spaces ensuring that the color is adapted using chromatic adaptation.

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

@ -3,10 +3,10 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
using Implementation;
using Spaces;
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion.Implementation.CieLab;
/// <summary>
/// Converts between color spaces ensuring that the color is adapted using chromatic adaptation.

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

@ -3,10 +3,9 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
using Implementation;
using Spaces;
using ImageSharp.Colors.Spaces;
/// <summary>
/// Converts between color spaces ensuring that the color is adapted using chromatic adaptation.

9
src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.cs

@ -3,11 +3,12 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
using System.Numerics;
using Implementation;
using Spaces;
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion.Implementation.Lms;
/// <summary>
/// Converts between color spaces ensuring that the color is adapted using chromatic adaptation.
@ -23,7 +24,7 @@ namespace ImageSharp.Colors.Conversion
private CieXyzAndLmsConverter cachedCieXyzAndLmsConverter;
/// <summary>
/// Initializes a new instance of the <see cref="ColorSpaceConverter"/> class.
/// Initializes a new instance of the <see cref="Spaces.Conversion.ColorSpaceConverter"/> class.
/// </summary>
public ColorSpaceConverter()
{

4
src/ImageSharp/Colors/Spaces/Conversion/IChromaticAdaptation.cs

@ -3,9 +3,9 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
using Spaces;
using ImageSharp.Colors.Spaces;
/// <summary>
/// Chromatic adaptation.

2
src/ImageSharp/Colors/Spaces/Conversion/IColorConversion.cs

@ -3,7 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
/// <summary>
/// Converts color between two color spaces.

5
src/ImageSharp/Colors/Spaces/Conversion/Implementation/CieLab/CieLabToCieXyzConverter.cs

@ -3,10 +3,11 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion.Implementation
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.CieLab
{
using System;
using Spaces;
using ImageSharp.Colors.Spaces;
/// <summary>
/// Converts from <see cref="CieLab"/> to <see cref="CieXyz"/>.

5
src/ImageSharp/Colors/Spaces/Conversion/Implementation/CieLab/CieXyzToCieLabConverter.cs

@ -3,10 +3,11 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion.Implementation
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.CieLab
{
using System;
using Spaces;
using ImageSharp.Colors.Spaces;
/// <summary>
/// Converts from <see cref="CieXyz"/> to <see cref="CieLab"/>.

5
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Lms/CieXyzAndLmsConverter.cs

@ -3,10 +3,11 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion.Implementation
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Lms
{
using System.Numerics;
using Spaces;
using ImageSharp.Colors.Spaces;
/// <summary>
/// Color converter between CIE XYZ and LMS

6
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Lms/LmsAdaptationMatrix.cs

@ -4,7 +4,7 @@
// </copyright>
// ReSharper disable InconsistentNaming
namespace ImageSharp.Colors.Conversion.Implementation
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Lms
{
using System.Numerics;
@ -13,7 +13,7 @@ namespace ImageSharp.Colors.Conversion.Implementation
/// Used in <see cref="IChromaticAdaptation"/>
/// </summary>
/// <remarks>
/// AdaptionMatrix3X3 data obtained from:
/// Matrix data obtained from:
/// Two New von Kries Based Chromatic Adaptation Transforms Found by Numerical Optimization
/// S. Bianco, R. Schettini
/// DISCo, Department of Informatics, Systems and Communication, University of Milan-Bicocca, viale Sarca 336, 20126 Milan, Italy
@ -98,4 +98,4 @@ namespace ImageSharp.Colors.Conversion.Implementation
M44 = 1F
};
}
}
}

48
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/GammaCompanding.cs

@ -0,0 +1,48 @@
// <copyright file="GammaCompanding.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb
{
using System;
using System.Runtime.CompilerServices;
/// <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 (float)Math.Pow(channel, this.Gamma);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return (float)Math.Pow(channel, 1 / this.Gamma);
}
}
}

37
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/LCompanding.cs

@ -0,0 +1,37 @@
// <copyright file="LCompanding.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb
{
using System;
using System.Runtime.CompilerServices;
/// <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 : (float)Math.Pow((channel + 0.16) / 1.16, 3);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel <= CieConstants.Epsilon
? channel * CieConstants.Kappa / 100F
: (float)Math.Pow(1.16 * channel, 0.333333333333333D) - 0.16F;
}
}
}

107
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/RGBPrimariesChromaticityCoordinates.cs

@ -0,0 +1,107 @@
// <copyright file="RgbPrimariesChromaticityCoordinates.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb
{
using System;
/// <summary>
/// Represents the chromaticity coordinates of RGB primaries.
/// One of the specifiers of <see cref="IRgbWorkingSpace"/>.
/// </summary>
public struct RgbPrimariesChromaticityCoordinates : IEquatable<RgbPrimariesChromaticityCoordinates>
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbPrimariesChromaticityCoordinates"/> struct.
/// </summary>
/// <param name="r">The chomaticity coordinates of the red channel.</param>
/// <param name="g">The chomaticity coordinates of the green channel.</param>
/// <param name="b">The chomaticity coordinates of the blue channel.</param>
public RgbPrimariesChromaticityCoordinates(CieXyChromaticityCoordinates r, CieXyChromaticityCoordinates g, CieXyChromaticityCoordinates b)
{
this.R = r;
this.G = g;
this.B = b;
}
/// <summary>
/// Gets the chomaticity coordinates of the red channel.
/// </summary>
public CieXyChromaticityCoordinates R { get; }
/// <summary>
/// Gets the chomaticity coordinates of the green channel.
/// </summary>
public CieXyChromaticityCoordinates G { get; }
/// <summary>
/// Gets the chomaticity coordinates of the blue channel.
/// </summary>
public CieXyChromaticityCoordinates B { get; }
/// <summary>
/// Compares two <see cref="CieLab"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="CieLab"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="CieLab"/> 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 ==(RgbPrimariesChromaticityCoordinates left, RgbPrimariesChromaticityCoordinates right)
{
return left.Equals(right);
}
/// <summary>
/// Compares two <see cref="CieLab"/> objects for inequality
/// </summary>
/// <param name="left">
/// The <see cref="CieLab"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="CieLab"/> 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 !=(RgbPrimariesChromaticityCoordinates left, RgbPrimariesChromaticityCoordinates right)
{
return !left.Equals(right);
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is RgbPrimariesChromaticityCoordinates)
{
return this.Equals((RgbPrimariesChromaticityCoordinates)obj);
}
return false;
}
/// <inheritdoc/>
public bool Equals(RgbPrimariesChromaticityCoordinates other)
{
return this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B);
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
int hashCode = this.R.GetHashCode();
hashCode = (hashCode * 397) ^ this.G.GetHashCode();
hashCode = (hashCode * 397) ^ this.B.GetHashCode();
return hashCode;
}
}
}
}

34
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/Rec2020Companding.cs

@ -0,0 +1,34 @@
// <copyright file="Rec2020Companding.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb
{
using System;
using System.Runtime.CompilerServices;
/// <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 : (float)Math.Pow((channel + 0.0993) / 1.0993, 1 / 0.45);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F;
}
}
}

33
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/Rec709Companding.cs

@ -0,0 +1,33 @@
// <copyright file="Rec2020Companding.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb
{
using System;
using System.Runtime.CompilerServices;
/// <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 : (float)Math.Pow((channel + 0.099) / 1.099, 1 / 0.45);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F;
}
}
}

107
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs

@ -0,0 +1,107 @@
// <copyright file="RgbWorkingSpace.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb
{
/// <summary>
/// Trivial implementation of <see cref="IRgbWorkingSpace"/>
/// </summary>
public struct RgbWorkingSpace : IRgbWorkingSpace
{
/// <summary>
/// Initializes a new instance of the <see cref="RgbWorkingSpace"/> struct.
/// </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)
{
if (obj is RgbWorkingSpace)
{
return this.Equals((RgbWorkingSpace)obj);
}
return false;
}
/// <inheritdoc/>
public bool Equals(IRgbWorkingSpace other)
{
// TODO: Object.Equals for ICompanding will be slow.
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;
}
}
}
}

35
src/ImageSharp/Colors/Spaces/Conversion/Implementation/Rgb/SRgbCompanding.cs

@ -0,0 +1,35 @@
// <copyright file="SRgbCompanding.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb
{
using System;
using System.Runtime.CompilerServices;
/// <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 : (float)Math.Pow((channel + 0.055) / 1.055, 2.4);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Compress(float channel)
{
return channel <= 0.0031308F ? 12.92F * channel : (1.055F * (float)Math.Pow(channel, 0.416666666666667D)) - 0.055F;
}
}
}

6
src/ImageSharp/Colors/Spaces/Conversion/VonKriesChromaticAdaptation.cs

@ -3,12 +3,12 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Colors.Conversion
namespace ImageSharp.Colors.Spaces.Conversion
{
using System.Numerics;
using Implementation;
using Spaces;
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion.Implementation.Lms;
/// <summary>
/// Basic implementation of the von Kries chromatic adaptation model

12
src/ImageSharp/Colors/Spaces/ICompanding.cs

@ -13,25 +13,25 @@ namespace ImageSharp.Colors.Spaces
public interface ICompanding
{
/// <summary>
/// Companded channel is made linear with respect to the energy.
/// Expands a companded channel to its linear equivalent with respect to the energy.
/// </summary>
/// <remarks>
/// For more info see:
/// http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
/// <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 InverseCompanding(float channel);
float Expand(float channel);
/// <summary>
/// Uncompanded channel (linear) is made nonlinear (depends on the RGB color system).
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent (depends on the RGB color system).
/// </summary>
/// <remarks>
/// For more info see:
/// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html
/// <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 Companding(float channel);
float Compress(float channel);
}
}

23
src/ImageSharp/Colors/Spaces/IRgbWorkingSpace.cs

@ -5,27 +5,30 @@
namespace ImageSharp.Colors.Spaces
{
using System;
using ImageSharp.Colors.Spaces.Conversion.Implementation;
using ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb;
/// <summary>
/// Encasulates the RGB working color space
/// </summary>
public interface IRgbWorkingSpace
public interface IRgbWorkingSpace : IEquatable<IRgbWorkingSpace>
{
/// <summary>
/// Gets the reference white of the color space
/// </summary>
CieXyz WhitePoint { get; }
// <summary>
// Gets Chromaticity coordinates of the primaries
// </summary>
// RGBPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <summary>
/// Gets the chromaticity coordinates of the primaries
/// </summary>
RgbPrimariesChromaticityCoordinates ChromaticityCoordinates { get; }
/// <summary>
/// Gets the companding function associated with the RGB color system.
/// Used for conversion to XYZ and backwards.
/// See this for more information:
/// http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
/// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html
/// Gets the companding function associated with the RGB color system. Used for conversion to XYZ and backwards.
/// <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"/>
/// </summary>
ICompanding Companding { get; }
}

117
src/ImageSharp/Colors/Spaces/RgbWorkingSpaces.cs

@ -0,0 +1,117 @@
// <copyright file="RgbWorkingSpaces.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// ReSharper disable InconsistentNaming
namespace ImageSharp.Colors.Spaces
{
using ImageSharp.Colors.Spaces.Conversion.Implementation.Rgb;
/// <summary>
/// Chromaticity coordinates taken from:
/// <see href="http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html"/>
/// </summary>
public static class RgbWorkingSpaces
{
/// <summary>
/// sRgb working space.
/// </summary>
/// <remarks>
/// 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)));
/// <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 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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
/// <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)));
}
}

3
tests/ImageSharp.Benchmarks/Color/ColorspaceConvert.cs

@ -5,9 +5,10 @@
using Colourful;
using Colourful.Conversion;
using ImageSharp.Colors.Conversion;
using ImageSharp.Colors.Spaces;
using ColorSpaceConverter = ImageSharp.Colors.Spaces.Conversion.ColorSpaceConverter;
public class ColorspaceConvert
{
private static readonly CieXyz CieXyz = new CieXyz(0.95047F, 1, 1.08883F);

3
tests/ImageSharp.Tests/Colors/Colorspaces/CieXyzAndCieLabConversionTest.cs

@ -1,8 +1,9 @@
namespace ImageSharp.Tests
{
using ImageSharp.Colors.Conversion;
using System.Collections.Generic;
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion;
using Xunit;
/// <summary>

3
tests/ImageSharp.Tests/Colors/Colorspaces/CieXyzAndLmsConversionTest.cs

@ -1,8 +1,9 @@
namespace ImageSharp.Tests
{
using ImageSharp.Colors.Conversion;
using System.Collections.Generic;
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion;
using Xunit;
/// <summary>

9
tests/ImageSharp.Tests/Colors/Colorspaces/ColorConverterAdaptTest.cs

@ -1,10 +1,11 @@
using ImageSharp.Colors.Conversion;
using ImageSharp.Colors.Conversion.Implementation;
using ImageSharp.Colors.Spaces;
namespace ImageSharp.Tests
{
using System.Collections.Generic;
using ImageSharp.Colors.Spaces;
using ImageSharp.Colors.Spaces.Conversion;
using ImageSharp.Colors.Spaces.Conversion.Implementation.Lms;
using Xunit;
public class ColorConverterAdaptTest

Loading…
Cancel
Save