diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
index 49c1da9f10..8e14274f66 100644
--- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
@@ -8,7 +8,7 @@
namespace SixLabors.ImageSharp.ColorSpaces
{
///
- /// Represents the coordinates of CIEXY chromaticity space
+ /// Represents the coordinates of CIEXY chromaticity space.
///
public readonly struct CieXyChromaticityCoordinates : IEquatable
{
diff --git a/src/ImageSharp/ColorSpaces/Companding/GammaCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/GammaCompanding.cs
index 13cca1582d..09b324b00f 100644
--- a/src/ImageSharp/ColorSpaces/Companding/GammaCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Companding/GammaCompanding.cs
@@ -7,7 +7,7 @@
namespace SixLabors.ImageSharp.ColorSpaces.Companding
{
///
- /// Implements gamma companding
+ /// Implements gamma companding.
///
///
///
diff --git a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
index 9e2cf8ad86..80b8aee7e7 100644
--- a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
@@ -8,7 +8,7 @@
namespace SixLabors.ImageSharp.ColorSpaces.Companding
{
///
- /// Implements L* companding
+ /// Implements L* companding.
///
///
/// For more info see:
@@ -24,7 +24,7 @@ public static class LCompanding
/// The representing the linear channel value.
[MethodImpl(InliningOptions.ShortMethod)]
public static float Expand(float channel)
- => channel <= 0.08 ? 100 * channel / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F);
+ => channel <= 0.08F ? (100F * channel) / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F);
///
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
@@ -33,6 +33,6 @@ public static float Expand(float channel)
/// The representing the nonlinear channel value.
[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;
+ => channel <= CieConstants.Epsilon ? (channel * CieConstants.Kappa) / 100F : (1.16F * MathF.Pow(channel, 0.3333333F)) - 0.16F;
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Companding/Rec2020Companding.cs b/src/ImageSharp/ColorSpaces/Companding/Rec2020Companding.cs
index a3a9121727..773fe81647 100644
--- a/src/ImageSharp/ColorSpaces/Companding/Rec2020Companding.cs
+++ b/src/ImageSharp/ColorSpaces/Companding/Rec2020Companding.cs
@@ -7,14 +7,19 @@
namespace SixLabors.ImageSharp.ColorSpaces.Companding
{
///
- /// Implements Rec. 2020 companding function (for 12-bits).
+ /// Implements Rec. 2020 companding function.
///
///
///
- /// For 10-bits, companding is identical to
///
public static class Rec2020Companding
{
+ private const float Alpha = 1.09929682680944F;
+ private const float AlphaMinusOne = Alpha - 1F;
+ private const float Beta = 0.018053968510807F;
+ private const float InverseBeta = Beta * 4.5F;
+ private const float Epsilon = 1 / 0.45F;
+
///
/// Expands a companded channel to its linear equivalent with respect to the energy.
///
@@ -22,7 +27,7 @@ public static class Rec2020Companding
/// The representing the linear channel value.
[MethodImpl(InliningOptions.ShortMethod)]
public static float Expand(float channel)
- => channel < 0.08145F ? channel / 4.5F : MathF.Pow((channel + 0.0993F) / 1.0993F, 2.222222F);
+ => channel < InverseBeta ? channel / 4.5F : MathF.Pow((channel + AlphaMinusOne) / Alpha, Epsilon);
///
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
@@ -31,6 +36,6 @@ public static float Expand(float channel)
/// The representing the nonlinear channel value.
[MethodImpl(InliningOptions.ShortMethod)]
public static float Compress(float channel)
- => channel < 0.0181F ? 4500F * channel : (1.0993F * channel) - 0.0993F;
+ => channel < Beta ? 4.5F * channel : (Alpha * MathF.Pow(channel, 0.45F)) - AlphaMinusOne;
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Companding/Rec709Companding.cs b/src/ImageSharp/ColorSpaces/Companding/Rec709Companding.cs
index e2e802d08a..edc0b9763f 100644
--- a/src/ImageSharp/ColorSpaces/Companding/Rec709Companding.cs
+++ b/src/ImageSharp/ColorSpaces/Companding/Rec709Companding.cs
@@ -14,6 +14,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
///
public static class Rec709Companding
{
+ private const float Epsilon = 1 / 0.45F;
+
///
/// Expands a companded channel to its linear equivalent with respect to the energy.
///
@@ -21,7 +23,7 @@ public static class Rec709Companding
/// The representing the linear channel value.
[MethodImpl(InliningOptions.ShortMethod)]
public static float Expand(float channel)
- => channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, 2.222222F);
+ => channel < 0.081F ? channel / 4.5F : MathF.Pow((channel + 0.099F) / 1.099F, Epsilon);
///
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
@@ -30,6 +32,6 @@ public static float Expand(float channel)
/// The representing the nonlinear channel value.
[MethodImpl(InliningOptions.ShortMethod)]
public static float Compress(float channel)
- => channel < 0.018F ? 4500F * channel : (1.099F * channel) - 0.099F;
+ => channel < 0.018F ? 4.5F * channel : (1.099F * MathF.Pow(channel, 0.45F)) - 0.099F;
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
index 3810736197..7f4abfa7bb 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
@@ -26,10 +26,8 @@ public partial class ColorSpaceConverter
/// The
public CieLch ToCieLch(in CieLab color)
{
- // Adaptation
CieLab adapted = this.Adapt(color);
- // Conversion
return CieLabToCieLchConverter.Convert(adapted);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
index f33d1ddcc9..7767b7b448 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
@@ -7,7 +7,7 @@
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
///
- /// Color converter between CIE XYZ and CIE xyY
+ /// Color converter between CIE XYZ and CIE xyY.
/// for formulas.
///
internal sealed class CieXyzAndCieXyyConverter
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs
index 3812cdbdd8..f166e4c14a 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs
@@ -28,11 +28,15 @@ public CieXyzToLinearRgbConverter()
public CieXyzToLinearRgbConverter(RgbWorkingSpaceBase workingSpace)
{
this.TargetWorkingSpace = workingSpace;
- this.conversionMatrix = GetRgbToCieXyzMatrix(workingSpace);
+
+ // Gets the inverted Rgb -> Xyz matrix
+ Matrix4x4.Invert(GetRgbToCieXyzMatrix(workingSpace), out Matrix4x4 inverted);
+
+ this.conversionMatrix = inverted;
}
///
- /// Gets the target working space
+ /// Gets the target working space.
///
public RgbWorkingSpaceBase TargetWorkingSpace { get; }
@@ -40,12 +44,12 @@ public CieXyzToLinearRgbConverter(RgbWorkingSpaceBase workingSpace)
/// Performs the conversion from the input to an instance of type.
///
/// The input color instance.
- /// The converted result
+ /// The converted result.
[MethodImpl(InliningOptions.ShortMethod)]
public LinearRgb Convert(in CieXyz input)
{
- Matrix4x4.Invert(this.conversionMatrix, out Matrix4x4 inverted);
- var vector = Vector3.Transform(input.ToVector3(), inverted);
+ var vector = Vector3.Transform(input.ToVector3(), this.conversionMatrix);
+
return new LinearRgb(vector, this.TargetWorkingSpace);
}
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
index 29fd32905b..0700dab43a 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
@@ -8,7 +8,7 @@
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
///
- /// Color converter between and
+ /// Color converter between and .
///
internal sealed class CmykAndRgbConverter
{
@@ -28,7 +28,7 @@ public Rgb Convert(in Cmyk input)
/// Performs the conversion from the input to an instance of type.
///
/// The input color instance.
- /// The converted result
+ /// The converted result.
[MethodImpl(InliningOptions.ShortMethod)]
public Cmyk Convert(in Rgb input)
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
index 1cc055bee2..8454430935 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
@@ -6,7 +6,7 @@
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
///
- /// Color converter between and
+ /// Color converter between and .
///
internal sealed class LinearRgbToRgbConverter
{
@@ -14,16 +14,15 @@ internal sealed class LinearRgbToRgbConverter
/// Performs the conversion from the input to an instance of type.
///
/// The input color instance.
- /// The converted result
+ /// The converted result.
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb Convert(in LinearRgb input)
{
- var vector = input.ToVector3();
- 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);
+ return new Rgb(
+ r: input.WorkingSpace.Compress(input.R),
+ g: input.WorkingSpace.Compress(input.G),
+ b: input.WorkingSpace.Compress(input.B),
+ workingSpace: input.WorkingSpace);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
index 03912a421e..4ddbe42e54 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
@@ -6,7 +6,7 @@
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
///
- /// Color converter between Rgb and LinearRgb
+ /// Color converter between Rgb and LinearRgb.
///
internal class RgbToLinearRgbConverter
{
@@ -14,16 +14,15 @@ internal class RgbToLinearRgbConverter
/// Performs the conversion from the input to an instance of type.
///
/// The input color instance.
- /// The converted result
+ /// The converted result.
[MethodImpl(InliningOptions.ShortMethod)]
public LinearRgb Convert(in Rgb input)
{
- var vector = input.ToVector3();
- 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);
+ return new LinearRgb(
+ r: input.WorkingSpace.Expand(input.R),
+ g: input.WorkingSpace.Expand(input.G),
+ b: input.WorkingSpace.Expand(input.B),
+ workingSpace: input.WorkingSpace);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
index 4ac3ad3cf9..ee15ffa508 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
@@ -19,7 +19,7 @@ internal sealed class YCbCrAndRgbConverter
/// Performs the conversion from the input to an instance of type.
///
/// The input color instance.
- /// The converted result
+ /// The converted result.
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb Convert(in YCbCr input)
{
@@ -38,7 +38,7 @@ public Rgb Convert(in YCbCr input)
/// Performs the conversion from the input to an instance of type.
///
/// The input color instance.
- /// The converted result
+ /// The converted result.
[MethodImpl(InliningOptions.ShortMethod)]
public YCbCr Convert(in Rgb input)
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
index 639d0b2933..c45dea3179 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
///
/// The gamma working space.
///
- public class GammaWorkingSpace : RgbWorkingSpaceBase
+ public sealed class GammaWorkingSpace : RgbWorkingSpaceBase
{
///
/// Initializes a new instance of the class.
diff --git a/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs b/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs
index b2ee030483..e1386e1a09 100644
--- a/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/Companding/CompandingTests.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces.Companding;
using Xunit;
@@ -10,9 +9,7 @@
namespace SixLabors.ImageSharp.Tests.Colorspaces.Companding
{
///
- /// Tests various companding algorithms. Numbers are hand calculated from formulas online.
- /// TODO: Oddly the formula for converting to/from Rec 2020 and 709 from Wikipedia seems to cause the value to
- /// fail a round trip. They're large spaces so this is a surprise. More reading required!!
+ /// Tests various companding algorithms. Expanded numbers are hand calculated from formulas online.
///
public class CompandingTests
{
@@ -24,7 +21,7 @@ public void Rec2020Companding_IsCorrect()
const float input = .667F;
float e = Rec2020Companding.Expand(input);
float c = Rec2020Companding.Compress(e);
- CompandingIsCorrectImpl(e, c, .4484759F, .3937096F);
+ CompandingIsCorrectImpl(e, c, .4484759F, input);
}
[Fact]
@@ -33,7 +30,7 @@ public void Rec709Companding_IsCorrect()
const float input = .667F;
float e = Rec709Companding.Expand(input);
float c = Rec709Companding.Compress(e);
- CompandingIsCorrectImpl(e, c, .4483577F, .3937451F);
+ CompandingIsCorrectImpl(e, c, .4483577F, input);
}
[Fact]
@@ -42,7 +39,7 @@ public void SRgbCompanding_IsCorrect()
const float input = .667F;
float e = SRgbCompanding.Expand(input);
float c = SRgbCompanding.Compress(e);
- CompandingIsCorrectImpl(e, c, .40242353F, .667F);
+ CompandingIsCorrectImpl(e, c, .40242353F, input);
}
[Theory]
@@ -98,7 +95,7 @@ public void GammaCompanding_IsCorrect()
const float input = .667F;
float e = GammaCompanding.Expand(input, gamma);
float c = GammaCompanding.Compress(e, gamma);
- CompandingIsCorrectImpl(e, c, .41027668F, .667F);
+ CompandingIsCorrectImpl(e, c, .41027668F, input);
}
[Fact]
@@ -107,7 +104,7 @@ public void LCompanding_IsCorrect()
const float input = .667F;
float e = LCompanding.Expand(input);
float c = LCompanding.Compress(e);
- CompandingIsCorrectImpl(e, c, .36236193F, .58908917F);
+ CompandingIsCorrectImpl(e, c, .36236193F, input);
}
private static void CompandingIsCorrectImpl(float e, float c, float expanded, float compressed)