From 0a5c84adbdedfa3b4d5a78776af82fa2a9ca936c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 29 Jul 2018 22:58:16 +0100 Subject: [PATCH] Make ColorSpaceConverter immutable. --- .../Conversion/ColorSpaceConverter.Adapt.cs | 37 ++++--- .../Conversion/ColorSpaceConverter.CieLab.cs | 8 +- .../Conversion/ColorSpaceConverter.CieLch.cs | 2 +- .../ColorSpaceConverter.CieLchuv.cs | 7 +- .../Conversion/ColorSpaceConverter.CieLuv.cs | 8 +- .../Conversion/ColorSpaceConverter.CieXyz.cs | 10 +- .../ColorSpaceConverter.HunterLab.cs | 6 +- .../ColorSpaceConverter.LinearRgb.cs | 6 +- .../Conversion/ColorSpaceConverter.Lms.cs | 2 +- .../Conversion/ColorSpaceConverter.cs | 98 +++++-------------- .../Conversion/ColorSpaceConverterOptions.cs | 55 +++++++++++ .../Implementation/CieXyzAndLmsConverter.cs | 20 +--- .../Color/RgbWorkingSpaceAdapt.cs | 2 +- .../Colorspaces/ColorSpaceEqualityTests.cs | 4 + .../CieXyzAndCieLabConversionTest.cs | 6 +- .../CieXyzAndCieLuvConversionTest.cs | 6 +- .../CieXyzAndHunterLabConversionTest.cs | 9 +- .../Conversion/ColorConverterAdaptTest.cs | 20 ++-- .../Conversion/RgbAndCieXyzConversionTest.cs | 12 ++- 19 files changed, 165 insertions(+), 153 deletions(-) create mode 100644 src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs index 055e9fbfc7..29d4fca5e4 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation; namespace SixLabors.ImageSharp.ColorSpaces.Conversion @@ -14,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { /// /// Performs chromatic adaptation of given color. - /// Target white point is . + /// Target white point is . /// /// The color to adapt /// The white point to adapt for @@ -22,11 +21,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public CieXyz Adapt(in CieXyz color, in CieXyz sourceWhitePoint) { this.CheckChromaticAdaptation(); - return this.ChromaticAdaptation.Transform(color, sourceWhitePoint, this.WhitePoint); + return this.chromaticAdaptation.Transform(color, sourceWhitePoint, this.whitePoint); } /// - /// Adapts color from the source white point to white point set in . + /// Adapts color from the source white point to white point set in . /// /// The color to adapt /// The adapted color @@ -34,7 +33,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { this.CheckChromaticAdaptation(); - if (color.WhitePoint.Equals(this.TargetLabWhitePoint)) + if (color.WhitePoint.Equals(this.targetLabWhitePoint)) { return color; } @@ -44,7 +43,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Adapts color from the source white point to white point set in . + /// Adapts color from the source white point to white point set in . /// /// The color to adapt /// The adapted color @@ -52,7 +51,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { this.CheckChromaticAdaptation(); - if (color.WhitePoint.Equals(this.TargetLabWhitePoint)) + if (color.WhitePoint.Equals(this.targetLabWhitePoint)) { return color; } @@ -62,7 +61,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Adapts color from the source white point to white point set in . + /// Adapts color from the source white point to white point set in . /// /// The color to adapt /// The adapted color @@ -70,7 +69,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { this.CheckChromaticAdaptation(); - if (color.WhitePoint.Equals(this.TargetLabWhitePoint)) + if (color.WhitePoint.Equals(this.targetLabWhitePoint)) { return color; } @@ -80,7 +79,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Adapts color from the source white point to white point set in . + /// Adapts color from the source white point to white point set in . /// /// The color to adapt /// The adapted color @@ -88,7 +87,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { this.CheckChromaticAdaptation(); - if (color.WhitePoint.Equals(this.TargetLuvWhitePoint)) + if (color.WhitePoint.Equals(this.targetLuvWhitePoint)) { return color; } @@ -98,7 +97,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Adapts color from the source white point to white point set in . + /// Adapts color from the source white point to white point set in . /// /// The color to adapt /// The adapted color @@ -106,7 +105,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { this.CheckChromaticAdaptation(); - if (color.WhitePoint.Equals(this.TargetHunterLabWhitePoint)) + if (color.WhitePoint.Equals(this.targetHunterLabWhitePoint)) { return color; } @@ -116,7 +115,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion } /// - /// Adapts a color from the source working space to working space set in . + /// Adapts a color from the source working space to working space set in . /// /// The color to adapt /// The adapted color @@ -124,7 +123,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { this.CheckChromaticAdaptation(); - if (color.WorkingSpace.Equals(this.TargetRgbWorkingSpace)) + if (color.WorkingSpace.Equals(this.targetRgbWorkingSpace)) { return color; } @@ -134,15 +133,15 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion CieXyz unadapted = converterToXYZ.Convert(color); // Adaptation - CieXyz adapted = this.ChromaticAdaptation.Transform(unadapted, color.WorkingSpace.WhitePoint, this.TargetRgbWorkingSpace.WhitePoint); + CieXyz adapted = this.chromaticAdaptation.Transform(unadapted, color.WorkingSpace.WhitePoint, this.targetRgbWorkingSpace.WhitePoint); // Conversion back to RGB - CieXyzToLinearRgbConverter converterToRGB = this.GetCieXyxToLinearRgbConverter(this.TargetRgbWorkingSpace); + CieXyzToLinearRgbConverter converterToRGB = this.GetCieXyxToLinearRgbConverter(this.targetRgbWorkingSpace); return converterToRGB.Convert(adapted); } /// - /// Adapts an color from the source working space to working space set in . + /// Adapts an color from the source working space to working space set in . /// /// The color to adapt /// The adapted color @@ -157,7 +156,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion { const string NoAdapterMessage = "Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point."; - if (!this.IsChromaticAdaptationPerformed) + if (!this.performChromaticAdaptation) { throw new InvalidOperationException(NoAdapterMessage); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs index 37f0e8567d..9095d3f59c 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion // Conversion (perserving white point) CieLab unadapted = CieLchToCieLabConverter.Convert(color); - if (!this.IsChromaticAdaptationPerformed) + if (!this.performChromaticAdaptation) { return unadapted; } @@ -165,12 +165,12 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public CieLab ToCieLab(in CieXyz color) { // Adaptation - CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed - ? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetLabWhitePoint) + CieXyz adapted = !this.whitePoint.Equals(this.targetLabWhitePoint) && this.performChromaticAdaptation + ? this.chromaticAdaptation.Transform(color, this.whitePoint, this.targetLabWhitePoint) : color; // Conversion - var converter = new CieXyzToCieLabConverter(this.TargetLabWhitePoint); + var converter = new CieXyzToCieLabConverter(this.targetLabWhitePoint); return converter.Convert(adapted); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs index 0f54471e60..b7b29109d8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public CieLch ToCieLch(in CieLab color) { // Adaptation - CieLab adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color; + CieLab adapted = this.performChromaticAdaptation ? this.Adapt(color) : color; // Conversion return CieLabToCieLchConverter.Convert(adapted); diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs index 77e707621a..1f831984af 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs @@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public CieLchuv ToCieLchuv(in CieLuv color) { // Adaptation - CieLuv adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color; + CieLuv adapted = this.performChromaticAdaptation ? this.Adapt(color) : color; // Conversion return CieLuvToCieLchuvConverter.Convert(adapted); @@ -388,7 +388,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// /// The color to convert. /// The - public CieLchuv ToCieLchuv(Rgb color) + public CieLchuv ToCieLchuv(in Rgb color) { var xyzColor = this.ToCieXyz(color); @@ -423,8 +423,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public CieLchuv ToCieLchuv(in YCbCr color) { - CieXyz xyzColor = this.ToCieXyz(color); - + var xyzColor = this.ToCieXyz(color); return this.ToCieLchuv(xyzColor); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs index a0dc4ea890..5b41ba51e1 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion // Conversion (perserving white point) CieLuv unadapted = CieLchuvToCieLuvConverter.Convert(color); - if (!this.IsChromaticAdaptationPerformed) + if (!this.performChromaticAdaptation) { return unadapted; } @@ -160,12 +160,12 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public CieLuv ToCieLuv(in CieXyz color) { // Adaptation - CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed - ? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetLabWhitePoint) + CieXyz adapted = !this.whitePoint.Equals(this.targetLabWhitePoint) && this.performChromaticAdaptation + ? this.chromaticAdaptation.Transform(color, this.whitePoint, this.targetLabWhitePoint) : color; // Conversion - var converter = new CieXyzToCieLuvConverter(this.TargetLuvWhitePoint); + var converter = new CieXyzToCieLuvConverter(this.targetLuvWhitePoint); return converter.Convert(adapted); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs index b29e249055..20aa359ca8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion CieXyz unadapted = CieLabToCieXyzConverter.Convert(color); // Adaptation - CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed + CieXyz adapted = color.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation ? unadapted : this.Adapt(unadapted, color.WhitePoint); @@ -141,7 +141,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion CieXyz unadapted = CieLuvToCieXyzConverter.Convert(color); // Adaptation - CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed + CieXyz adapted = color.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation ? unadapted : this.Adapt(unadapted, color.WhitePoint); @@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color); // Adaptation - CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed + CieXyz adapted = color.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation ? unadapted : this.Adapt(unadapted, color.WhitePoint); @@ -354,7 +354,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion CieXyz unadapted = converter.Convert(color); // Adaptation - return color.WorkingSpace.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed + return color.WorkingSpace.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation ? unadapted : this.Adapt(unadapted, color.WorkingSpace.WhitePoint); } @@ -388,7 +388,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public CieXyz ToCieXyz(in Lms color) { // Conversion - return this.cachedCieXyzAndLmsConverter.Convert(color); + return this.cieXyzAndLmsConverter.Convert(color); } /// diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs index a4a9aa24d1..bb3e1e4cee 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs @@ -181,12 +181,12 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public HunterLab ToHunterLab(in CieXyz color) { // Adaptation - CieXyz adapted = !this.WhitePoint.Equals(this.TargetHunterLabWhitePoint) && this.IsChromaticAdaptationPerformed - ? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetHunterLabWhitePoint) + CieXyz adapted = !this.whitePoint.Equals(this.targetHunterLabWhitePoint) && this.performChromaticAdaptation + ? this.chromaticAdaptation.Transform(color, this.whitePoint, this.targetHunterLabWhitePoint) : color; // Conversion - return new CieXyzToHunterLabConverter(this.TargetHunterLabWhitePoint).Convert(adapted); + return new CieXyzToHunterLabConverter(this.targetHunterLabWhitePoint).Convert(adapted); } /// diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs index f4a628cb8c..f95350b298 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs @@ -185,12 +185,12 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion public LinearRgb ToLinearRgb(in CieXyz color) { // Adaptation - CieXyz adapted = this.TargetRgbWorkingSpace.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed + CieXyz adapted = this.targetRgbWorkingSpace.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation ? color - : this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetRgbWorkingSpace.WhitePoint); + : this.chromaticAdaptation.Transform(color, this.whitePoint, this.targetRgbWorkingSpace.WhitePoint); // Conversion - CieXyzToLinearRgbConverter xyzConverter = this.GetCieXyxToLinearRgbConverter(this.TargetRgbWorkingSpace); + CieXyzToLinearRgbConverter xyzConverter = this.GetCieXyxToLinearRgbConverter(this.targetRgbWorkingSpace); return xyzConverter.Convert(adapted); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs index a328057ac2..840a994144 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs @@ -179,7 +179,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion /// The public Lms ToLms(in CieXyz color) { - return this.cachedCieXyzAndLmsConverter.Convert(color); + return this.cieXyzAndLmsConverter.Convert(color); } /// diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs index 7de590e225..e26ef8da11 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs @@ -7,94 +7,46 @@ using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation; namespace SixLabors.ImageSharp.ColorSpaces.Conversion { /// - /// Converts between color spaces ensuring that the color is adapted using chromatic adaptation. + /// Provides methods to allow the conversion of color values into different color spaces. /// public partial class ColorSpaceConverter { - /// - /// The default whitepoint used for converting to CieLab - /// - public static readonly CieXyz DefaultWhitePoint = Illuminants.D65; + // Options. + private CieXyz whitePoint; + private CieXyz targetLuvWhitePoint; + private CieXyz targetLabWhitePoint; + private CieXyz targetHunterLabWhitePoint; + private RgbWorkingSpace targetRgbWorkingSpace; + private IChromaticAdaptation chromaticAdaptation; + private bool performChromaticAdaptation; + private Matrix4x4 lmsAdaptationMatrix; - private Matrix4x4 transformationMatrix; - - private CieXyzAndLmsConverter cachedCieXyzAndLmsConverter; + private CieXyzAndLmsConverter cieXyzAndLmsConverter; /// /// Initializes a new instance of the class. /// public ColorSpaceConverter() + : this(new ColorSpaceConverterOptions()) { - // Note the order here this is important. - this.WhitePoint = DefaultWhitePoint; - this.LmsAdaptationMatrix = CieXyzAndLmsConverter.DefaultTransformationMatrix; - this.ChromaticAdaptation = new VonKriesChromaticAdaptation(this.cachedCieXyzAndLmsConverter); - this.TargetLuvWhitePoint = CieLuv.DefaultWhitePoint; - this.TargetLabWhitePoint = CieLab.DefaultWhitePoint; - this.TargetHunterLabWhitePoint = HunterLab.DefaultWhitePoint; - this.TargetRgbWorkingSpace = Rgb.DefaultWorkingSpace; } /// - /// Gets or sets the white point used for chromatic adaptation in conversions from/to XYZ color space. - /// When null, no adaptation will be performed. - /// - public CieXyz WhitePoint { get; set; } - - /// - /// Gets or sets the white point used *when creating* Luv/LChuv colors. (Luv/LChuv colors on the input already contain the white point information) - /// Defaults to: . - /// - public CieXyz TargetLuvWhitePoint { get; set; } - - /// - /// Gets or sets the white point used *when creating* Lab/LChab colors. (Lab/LChab colors on the input already contain the white point information) - /// Defaults to: . - /// - public CieXyz TargetLabWhitePoint { get; set; } - - /// - /// Gets or sets the white point used *when creating* HunterLab colors. (HunterLab colors on the input already contain the white point information) - /// Defaults to: . - /// - public CieXyz TargetHunterLabWhitePoint { get; set; } - - /// - /// Gets or sets the target working space used *when creating* RGB colors. (RGB colors on the input already contain the working space information) - /// Defaults to: . - /// - public RgbWorkingSpace TargetRgbWorkingSpace { get; set; } - - /// - /// Gets or sets the chromatic adaptation method used. When null, no adaptation will be performed. - /// - public IChromaticAdaptation ChromaticAdaptation { get; set; } - - /// - /// Gets or sets transformation matrix used in conversion to , - /// also used in the default Von Kries Chromatic Adaptation method. + /// Initializes a new instance of the class. /// - public Matrix4x4 LmsAdaptationMatrix + /// The configuration options. + public ColorSpaceConverter(ColorSpaceConverterOptions options) { - get => this.transformationMatrix; - - set - { - this.transformationMatrix = value; - if (this.cachedCieXyzAndLmsConverter == null) - { - this.cachedCieXyzAndLmsConverter = new CieXyzAndLmsConverter(value); - } - else - { - this.cachedCieXyzAndLmsConverter.TransformationMatrix = value; - } - } + Guard.NotNull(options, nameof(options)); + this.whitePoint = options.WhitePoint; + this.targetLuvWhitePoint = options.TargetLuvWhitePoint; + this.targetLabWhitePoint = options.TargetLabWhitePoint; + this.targetHunterLabWhitePoint = options.TargetHunterLabWhitePoint; + this.targetRgbWorkingSpace = options.TargetRgbWorkingSpace; + this.chromaticAdaptation = options.ChromaticAdaptation; + this.performChromaticAdaptation = this.chromaticAdaptation != null; + this.lmsAdaptationMatrix = options.LmsAdaptationMatrix; + this.cieXyzAndLmsConverter = new CieXyzAndLmsConverter(this.lmsAdaptationMatrix); } - - /// - /// Gets a value indicating whether chromatic adaptation has been performed. - /// - private bool IsChromaticAdaptationPerformed => this.ChromaticAdaptation != null; } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs new file mode 100644 index 0000000000..65fe799949 --- /dev/null +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs @@ -0,0 +1,55 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; +using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation; + +namespace SixLabors.ImageSharp.ColorSpaces.Conversion +{ + /// + /// Configuration options for the class. + /// + public class ColorSpaceConverterOptions + { + /// + /// Gets or sets the white point used for chromatic adaptation in conversions from/to XYZ color space. + /// When default, no adaptation will be performed. + /// Defaults to: . + /// + public CieXyz WhitePoint { get; set; } = CieLuv.DefaultWhitePoint; + + /// + /// Gets or sets the white point used *when creating* Luv/LChuv colors. (Luv/LChuv colors on the input already contain the white point information) + /// Defaults to: . + /// + public CieXyz TargetLuvWhitePoint { get; set; } = CieLuv.DefaultWhitePoint; + + /// + /// Gets or sets the white point used *when creating* Lab/LChab colors. (Lab/LChab colors on the input already contain the white point information) + /// Defaults to: . + /// + public CieXyz TargetLabWhitePoint { get; set; } = CieLab.DefaultWhitePoint; + + /// + /// Gets or sets the white point used *when creating* HunterLab colors. (HunterLab colors on the input already contain the white point information) + /// Defaults to: . + /// + public CieXyz TargetHunterLabWhitePoint { get; set; } = HunterLab.DefaultWhitePoint; + + /// + /// Gets or sets the target working space used *when creating* RGB colors. (RGB colors on the input already contain the working space information) + /// Defaults to: . + /// + public RgbWorkingSpace TargetRgbWorkingSpace { get; set; } = Rgb.DefaultWorkingSpace; + + /// + /// Gets or sets the chromatic adaptation method used. When null, no adaptation will be performed. + /// + public IChromaticAdaptation ChromaticAdaptation { get; set; } = new VonKriesChromaticAdaptation(); + + /// + /// Gets or sets transformation matrix used in conversion to and from . + /// + public Matrix4x4 LmsAdaptationMatrix { get; set; } = CieXyzAndLmsConverter.DefaultTransformationMatrix; + } +} \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs index 405ccc8194..3bbf1e84aa 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs @@ -39,24 +39,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation [MethodImpl(MethodImplOptions.AggressiveInlining)] public CieXyzAndLmsConverter(Matrix4x4 transformationMatrix) { - this.TransformationMatrix = transformationMatrix; - } - - /// - /// Gets or sets the transformation matrix used for the conversion (definition of the cone response domain). - /// - /// - public Matrix4x4 TransformationMatrix - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => this.transformationMatrix; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - set - { - this.transformationMatrix = value; - Matrix4x4.Invert(this.transformationMatrix, out this.inverseTransformationMatrix); - } + this.transformationMatrix = transformationMatrix; + Matrix4x4.Invert(this.transformationMatrix, out this.inverseTransformationMatrix); } /// diff --git a/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs b/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs index eba6b5d9be..92008f6e20 100644 --- a/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs +++ b/tests/ImageSharp.Benchmarks/Color/RgbWorkingSpaceAdapt.cs @@ -14,7 +14,7 @@ private static readonly RGBColor RGBColor = new RGBColor(0.206162, 0.260277, 0.746717, RGBWorkingSpaces.WideGamutRGB); - private static readonly ColorSpaceConverter ColorSpaceConverter = new ColorSpaceConverter { TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb }; + private static readonly ColorSpaceConverter ColorSpaceConverter = new ColorSpaceConverter(new ColorSpaceConverterOptions { TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb }); private static readonly ColourfulConverter ColourfulConverter = new ColourfulConverter { TargetRGBWorkingSpace = RGBWorkingSpaces.sRGB }; diff --git a/tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs b/tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs index 1e629b4553..ba0f11eea8 100644 --- a/tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs +++ b/tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs @@ -17,6 +17,10 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces { var x = default(CieLab); var y = new CieLab(Vector3.One); + + Assert.True(default(CieLab) == default(CieLab)); + Assert.True(default(CieLab) != new CieLab(1, 0, 1)); + Assert.False(default(CieLab) == new CieLab(1, 0, 1)); Assert.Equal(default(CieLab), default(CieLab)); Assert.Equal(new CieLab(1, 0, 1), new CieLab(1, 0, 1)); Assert.Equal(new CieLab(Vector3.One), new CieLab(Vector3.One)); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieLabConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieLabConversionTest.cs index 66f7e75ada..746e37c0e6 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieLabConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieLabConversionTest.cs @@ -35,7 +35,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new CieLab(l, a, b, Illuminants.D65); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; + var converter = new ColorSpaceConverter(options); var expected = new CieXyz(x, y, z); Span inputSpan = new CieLab[5]; @@ -70,7 +71,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new CieXyz(x, y, z); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; + var converter = new ColorSpaceConverter(options); var expected = new CieLab(l, a, b); Span inputSpan = new CieXyz[5]; diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieLuvConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieLuvConversionTest.cs index a6a7ee7aec..c0856a2bc1 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieLuvConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndCieLuvConversionTest.cs @@ -34,7 +34,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new CieLuv(l, u, v, Illuminants.D65); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; + var converter = new ColorSpaceConverter(options); var expected = new CieXyz(x, y, z); Span inputSpan = new CieLuv[5]; @@ -69,7 +70,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new CieXyz(x, y, z); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; + var converter = new ColorSpaceConverter(options); var expected = new CieLuv(l, u, v); Span inputSpan = new CieXyz[5]; diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndHunterLabConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndHunterLabConversionTest.cs index 2251777927..d162940151 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndHunterLabConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/CieXyzAndHunterLabConversionTest.cs @@ -29,7 +29,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new HunterLab(l, a, b); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.C }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.C }; + var converter = new ColorSpaceConverter(options); var expected = new CieXyz(x, y, z); Span inputSpan = new HunterLab[5]; @@ -60,7 +61,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new HunterLab(l, a, b); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65 }; + var converter = new ColorSpaceConverter(options); var expected = new CieXyz(x, y, z); Span inputSpan = new HunterLab[5]; @@ -91,7 +93,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new CieXyz(x, y, z); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65 }; + var converter = new ColorSpaceConverter(options); var expected = new HunterLab(l, a, b); Span inputSpan = new CieXyz[5]; diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/ColorConverterAdaptTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/ColorConverterAdaptTest.cs index f5dc6f6118..af9b8c5b33 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/ColorConverterAdaptTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/ColorConverterAdaptTest.cs @@ -27,7 +27,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion // Arrange var input = new Rgb(r1, g1, b1, RgbWorkingSpaces.WideGamutRgb); var expected = new Rgb(r2, g2, b2, RgbWorkingSpaces.SRgb); - var converter = new ColorSpaceConverter { TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb }; + var options = new ColorSpaceConverterOptions { TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb }; + var converter = new ColorSpaceConverter(options); // Action Rgb actual = converter.Adapt(input); @@ -46,7 +47,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion // Arrange var input = new Rgb(r1, g1, b1, RgbWorkingSpaces.SRgb); var expected = new Rgb(r2, g2, b2, RgbWorkingSpaces.WideGamutRgb); - var converter = new ColorSpaceConverter { TargetRgbWorkingSpace = RgbWorkingSpaces.WideGamutRgb }; + var options = new ColorSpaceConverterOptions { TargetRgbWorkingSpace = RgbWorkingSpaces.WideGamutRgb }; + var converter = new ColorSpaceConverter(options); // Action Rgb actual = converter.Adapt(input); @@ -64,7 +66,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion // Arrange var input = new CieLab(l1, a1, b1, Illuminants.D65); var expected = new CieLab(l2, a2, b2); - var converter = new ColorSpaceConverter { TargetLabWhitePoint = Illuminants.D50 }; + var options = new ColorSpaceConverterOptions { TargetLabWhitePoint = Illuminants.D50 }; + var converter = new ColorSpaceConverter(options); // Action CieLab actual = converter.Adapt(input); @@ -81,7 +84,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion // Arrange var input = new CieXyz(x1, y1, z1); var expected = new CieXyz(x2, y2, z2); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D50 }; + var converter = new ColorSpaceConverter(options); // Action CieXyz actual = converter.Adapt(input, Illuminants.D65); @@ -98,12 +102,14 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion // Arrange var input = new CieXyz(x1, y1, z1); var expected = new CieXyz(x2, y2, z2); - var converter = new ColorSpaceConverter + var options = new ColorSpaceConverterOptions { ChromaticAdaptation = new VonKriesChromaticAdaptation(LmsAdaptationMatrix.XyzScaling), WhitePoint = Illuminants.D50 }; + var converter = new ColorSpaceConverter(options); + // Action CieXyz actual = converter.Adapt(input, Illuminants.D65); @@ -119,12 +125,14 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion // Arrange var input = new CieXyz(x1, y1, z1); var expected = new CieXyz(x2, y2, z2); - var converter = new ColorSpaceConverter + var options = new ColorSpaceConverterOptions { ChromaticAdaptation = new VonKriesChromaticAdaptation(LmsAdaptationMatrix.XyzScaling), WhitePoint = Illuminants.D50 }; + var converter = new ColorSpaceConverter(options); + // Action CieXyz actual = converter.Adapt(input, Illuminants.D65); diff --git a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndCieXyzConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndCieXyzConversionTest.cs index ea1d0db00f..a3b0cbd953 100644 --- a/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndCieXyzConversionTest.cs +++ b/tests/ImageSharp.Tests/Colorspaces/Conversion/RgbAndCieXyzConversionTest.cs @@ -34,7 +34,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new CieXyz(x, y, z); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D50, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb }; + var converter = new ColorSpaceConverter(options); var expected = new Rgb(r, g, b); Span inputSpan = new CieXyz[5]; @@ -72,7 +73,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new CieXyz(x, y, z); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb }; + var converter = new ColorSpaceConverter(options); var expected = new Rgb(r, g, b); Span inputSpan = new CieXyz[5]; @@ -109,7 +111,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new Rgb(r, g, b); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D50 }; + var converter = new ColorSpaceConverter(options); var expected = new CieXyz(x, y, z); Span inputSpan = new Rgb[5]; @@ -145,7 +148,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces.Conversion { // Arrange var input = new Rgb(r, g, b); - var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 }; + var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65 }; + var converter = new ColorSpaceConverter(options); var expected = new CieXyz(x, y, z); Span inputSpan = new Rgb[5];