diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.CalculationType.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.CalculationType.cs index 187b17866..b3e26e2a2 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.CalculationType.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.CalculationType.cs @@ -1,15 +1,14 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal partial class CurveCalculator { - internal partial class CurveCalculator + private enum CalculationType { - private enum CalculationType - { - Identity, - Gamma, - Lut, - } + Identity, + Gamma, + Lut, } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.cs index 976ff2a85..48213a486 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.cs @@ -1,56 +1,54 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using System; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal partial class CurveCalculator : ISingleCalculator { - internal partial class CurveCalculator : ISingleCalculator - { - private LutCalculator lutCalculator; - private float gamma; - private CalculationType type; + private LutCalculator lutCalculator; + private float gamma; + private CalculationType type; - public CurveCalculator(IccCurveTagDataEntry entry, bool inverted) + public CurveCalculator(IccCurveTagDataEntry entry, bool inverted) + { + if (entry.IsIdentityResponse) + { + this.type = CalculationType.Identity; + } + else if (entry.IsGamma) { - if (entry.IsIdentityResponse) + this.gamma = entry.Gamma; + if (inverted) { - this.type = CalculationType.Identity; + this.gamma = 1f / this.gamma; } - else if (entry.IsGamma) - { - this.gamma = entry.Gamma; - if (inverted) - { - this.gamma = 1f / this.gamma; - } - this.type = CalculationType.Gamma; - } - else - { - this.lutCalculator = new LutCalculator(entry.CurveData, inverted); - this.type = CalculationType.Lut; - } + this.type = CalculationType.Gamma; + } + else + { + this.lutCalculator = new LutCalculator(entry.CurveData, inverted); + this.type = CalculationType.Lut; } + } - public float Calculate(float value) + public float Calculate(float value) + { + switch (this.type) { - switch (this.type) - { - case CalculationType.Identity: - return value; + case CalculationType.Identity: + return value; - case CalculationType.Gamma: - return MathF.Pow(value, this.gamma); + case CalculationType.Gamma: + return MathF.Pow(value, this.gamma); - case CalculationType.Lut: - return this.lutCalculator.Calculate(value); + case CalculationType.Lut: + return this.lutCalculator.Calculate(value); - default: - throw new InvalidOperationException("Invalid calculation type"); - } + default: + throw new InvalidOperationException("Invalid calculation type"); } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/GrayTrcCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/GrayTrcCalculator.cs index af1e24e20..1c68668d2 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/GrayTrcCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/GrayTrcCalculator.cs @@ -5,21 +5,20 @@ using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal class GrayTrcCalculator : IVector4Calculator { - internal class GrayTrcCalculator : IVector4Calculator - { - private TrcCalculator calculator; + private TrcCalculator calculator; - public GrayTrcCalculator(IccTagDataEntry grayTrc, bool toPcs) - { - this.calculator = new TrcCalculator(new IccTagDataEntry[] { grayTrc }, !toPcs); - } + public GrayTrcCalculator(IccTagDataEntry grayTrc, bool toPcs) + { + this.calculator = new TrcCalculator(new IccTagDataEntry[] { grayTrc }, !toPcs); + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 Calculate(Vector4 value) - { - return this.calculator.Calculate(value); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 Calculate(Vector4 value) + { + return this.calculator.Calculate(value); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ISingleCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ISingleCalculator.cs index 570415a69..3b4b4b51d 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ISingleCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ISingleCalculator.cs @@ -1,18 +1,17 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Represents an ICC calculator with a single floating point value and result +/// +internal interface ISingleCalculator { /// - /// Represents an ICC calculator with a single floating point value and result + /// Calculates a result from the given value /// - internal interface ISingleCalculator - { - /// - /// Calculates a result from the given value - /// - /// The input value - /// The calculated result - float Calculate(float value); - } + /// The input value + /// The calculated result + float Calculate(float value); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/IVector4Calculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/IVector4Calculator.cs index cf30c634c..5baa4666c 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/IVector4Calculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/IVector4Calculator.cs @@ -3,18 +3,17 @@ using System.Numerics; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Represents an ICC calculator with values and results +/// +internal interface IVector4Calculator { /// - /// Represents an ICC calculator with values and results + /// Calculates a result from the given values /// - internal interface IVector4Calculator - { - /// - /// Calculates a result from the given values - /// - /// The input values - /// The calculated result - Vector4 Calculate(Vector4 value); - } + /// The input values + /// The calculated result + Vector4 Calculate(Vector4 value); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.CalculationType.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.CalculationType.cs index a2a060eb9..7473fd7a0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.CalculationType.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.CalculationType.cs @@ -1,19 +1,18 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal partial class LutABCalculator { - internal partial class LutABCalculator + private enum CalculationType { - private enum CalculationType - { - AtoB = 1 << 3, - BtoA = 1 << 4, + AtoB = 1 << 3, + BtoA = 1 << 4, - SingleCurve = 1, - CurveMatrix = 2, - CurveClut = 3, - Full = 4, - } + SingleCurve = 1, + CurveMatrix = 2, + CurveClut = 3, + Full = 4, } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs index 0a7c774a1..5ea734d71 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs @@ -5,131 +5,130 @@ using System; using System.Numerics; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal partial class LutABCalculator : IVector4Calculator { - internal partial class LutABCalculator : IVector4Calculator + private CalculationType type; + private TrcCalculator curveACalculator; + private TrcCalculator curveBCalculator; + private TrcCalculator curveMCalculator; + private MatrixCalculator matrixCalculator; + private ClutCalculator clutCalculator; + + public LutABCalculator(IccLutAToBTagDataEntry entry) + { + Guard.NotNull(entry, nameof(entry)); + this.Init(entry.CurveA, entry.CurveB, entry.CurveM, entry.Matrix3x1, entry.Matrix3x3, entry.ClutValues); + this.type |= CalculationType.AtoB; + } + + public LutABCalculator(IccLutBToATagDataEntry entry) + { + Guard.NotNull(entry, nameof(entry)); + this.Init(entry.CurveA, entry.CurveB, entry.CurveM, entry.Matrix3x1, entry.Matrix3x3, entry.ClutValues); + this.type |= CalculationType.BtoA; + } + + public Vector4 Calculate(Vector4 value) { - private CalculationType type; - private TrcCalculator curveACalculator; - private TrcCalculator curveBCalculator; - private TrcCalculator curveMCalculator; - private MatrixCalculator matrixCalculator; - private ClutCalculator clutCalculator; - - public LutABCalculator(IccLutAToBTagDataEntry entry) + switch (this.type) + { + case CalculationType.Full | CalculationType.AtoB: + value = this.curveACalculator.Calculate(value); + value = this.clutCalculator.Calculate(value); + value = this.curveMCalculator.Calculate(value); + value = this.matrixCalculator.Calculate(value); + return this.curveBCalculator.Calculate(value); + + case CalculationType.Full | CalculationType.BtoA: + value = this.curveBCalculator.Calculate(value); + value = this.matrixCalculator.Calculate(value); + value = this.curveMCalculator.Calculate(value); + value = this.clutCalculator.Calculate(value); + return this.curveACalculator.Calculate(value); + + case CalculationType.CurveClut | CalculationType.AtoB: + value = this.curveACalculator.Calculate(value); + value = this.clutCalculator.Calculate(value); + return this.curveBCalculator.Calculate(value); + + case CalculationType.CurveClut | CalculationType.BtoA: + value = this.curveBCalculator.Calculate(value); + value = this.clutCalculator.Calculate(value); + return this.curveACalculator.Calculate(value); + + case CalculationType.CurveMatrix | CalculationType.AtoB: + value = this.curveMCalculator.Calculate(value); + value = this.matrixCalculator.Calculate(value); + return this.curveBCalculator.Calculate(value); + + case CalculationType.CurveMatrix | CalculationType.BtoA: + value = this.curveBCalculator.Calculate(value); + value = this.matrixCalculator.Calculate(value); + return this.curveMCalculator.Calculate(value); + + case CalculationType.SingleCurve | CalculationType.AtoB: + case CalculationType.SingleCurve | CalculationType.BtoA: + return this.curveBCalculator.Calculate(value); + + default: + throw new InvalidOperationException("Invalid calculation type"); + } + } + + private void Init(IccTagDataEntry[] curveA, IccTagDataEntry[] curveB, IccTagDataEntry[] curveM, Vector3? matrix3x1, Matrix4x4? matrix3x3, IccClut clut) + { + bool hasACurve = curveA != null; + bool hasBCurve = curveB != null; + bool hasMCurve = curveM != null; + bool hasMatrix = matrix3x1 != null && matrix3x3 != null; + bool hasClut = clut != null; + + if (hasBCurve && hasMatrix && hasMCurve && hasClut && hasACurve) + { + this.type = CalculationType.Full; + } + else if (hasBCurve && hasClut && hasACurve) + { + this.type = CalculationType.CurveClut; + } + else if (hasBCurve && hasMatrix && hasMCurve) + { + this.type = CalculationType.CurveMatrix; + } + else if (hasBCurve) + { + this.type = CalculationType.SingleCurve; + } + else + { + throw new InvalidIccProfileException("AToB or BToA tag has an invalid configuration"); + } + + if (hasACurve) + { + this.curveACalculator = new TrcCalculator(curveA, false); + } + + if (hasBCurve) { - Guard.NotNull(entry, nameof(entry)); - this.Init(entry.CurveA, entry.CurveB, entry.CurveM, entry.Matrix3x1, entry.Matrix3x3, entry.ClutValues); - this.type |= CalculationType.AtoB; + this.curveBCalculator = new TrcCalculator(curveB, false); } - public LutABCalculator(IccLutBToATagDataEntry entry) + if (hasMCurve) { - Guard.NotNull(entry, nameof(entry)); - this.Init(entry.CurveA, entry.CurveB, entry.CurveM, entry.Matrix3x1, entry.Matrix3x3, entry.ClutValues); - this.type |= CalculationType.BtoA; + this.curveMCalculator = new TrcCalculator(curveM, false); } - public Vector4 Calculate(Vector4 value) + if (hasMatrix) { - switch (this.type) - { - case CalculationType.Full | CalculationType.AtoB: - value = this.curveACalculator.Calculate(value); - value = this.clutCalculator.Calculate(value); - value = this.curveMCalculator.Calculate(value); - value = this.matrixCalculator.Calculate(value); - return this.curveBCalculator.Calculate(value); - - case CalculationType.Full | CalculationType.BtoA: - value = this.curveBCalculator.Calculate(value); - value = this.matrixCalculator.Calculate(value); - value = this.curveMCalculator.Calculate(value); - value = this.clutCalculator.Calculate(value); - return this.curveACalculator.Calculate(value); - - case CalculationType.CurveClut | CalculationType.AtoB: - value = this.curveACalculator.Calculate(value); - value = this.clutCalculator.Calculate(value); - return this.curveBCalculator.Calculate(value); - - case CalculationType.CurveClut | CalculationType.BtoA: - value = this.curveBCalculator.Calculate(value); - value = this.clutCalculator.Calculate(value); - return this.curveACalculator.Calculate(value); - - case CalculationType.CurveMatrix | CalculationType.AtoB: - value = this.curveMCalculator.Calculate(value); - value = this.matrixCalculator.Calculate(value); - return this.curveBCalculator.Calculate(value); - - case CalculationType.CurveMatrix | CalculationType.BtoA: - value = this.curveBCalculator.Calculate(value); - value = this.matrixCalculator.Calculate(value); - return this.curveMCalculator.Calculate(value); - - case CalculationType.SingleCurve | CalculationType.AtoB: - case CalculationType.SingleCurve | CalculationType.BtoA: - return this.curveBCalculator.Calculate(value); - - default: - throw new InvalidOperationException("Invalid calculation type"); - } + this.matrixCalculator = new MatrixCalculator(matrix3x3.Value, matrix3x1.Value); } - private void Init(IccTagDataEntry[] curveA, IccTagDataEntry[] curveB, IccTagDataEntry[] curveM, Vector3? matrix3x1, Matrix4x4? matrix3x3, IccClut clut) + if (hasClut) { - bool hasACurve = curveA != null; - bool hasBCurve = curveB != null; - bool hasMCurve = curveM != null; - bool hasMatrix = matrix3x1 != null && matrix3x3 != null; - bool hasClut = clut != null; - - if (hasBCurve && hasMatrix && hasMCurve && hasClut && hasACurve) - { - this.type = CalculationType.Full; - } - else if (hasBCurve && hasClut && hasACurve) - { - this.type = CalculationType.CurveClut; - } - else if (hasBCurve && hasMatrix && hasMCurve) - { - this.type = CalculationType.CurveMatrix; - } - else if (hasBCurve) - { - this.type = CalculationType.SingleCurve; - } - else - { - throw new InvalidIccProfileException("AToB or BToA tag has an invalid configuration"); - } - - if (hasACurve) - { - this.curveACalculator = new TrcCalculator(curveA, false); - } - - if (hasBCurve) - { - this.curveBCalculator = new TrcCalculator(curveB, false); - } - - if (hasMCurve) - { - this.curveMCalculator = new TrcCalculator(curveM, false); - } - - if (hasMatrix) - { - this.matrixCalculator = new MatrixCalculator(matrix3x3.Value, matrix3x1.Value); - } - - if (hasClut) - { - this.clutCalculator = new ClutCalculator(clut); - } + this.clutCalculator = new ClutCalculator(clut); } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs index 3e5717b1f..18fd622e6 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs @@ -4,70 +4,69 @@ using System; using System.Runtime.CompilerServices; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal class LutCalculator : ISingleCalculator { - internal class LutCalculator : ISingleCalculator + private float[] lut; + private bool inverse; + + public LutCalculator(float[] lut, bool inverse) { - private float[] lut; - private bool inverse; + Guard.NotNull(lut, nameof(lut)); - public LutCalculator(float[] lut, bool inverse) - { - Guard.NotNull(lut, nameof(lut)); + this.lut = lut; + this.inverse = inverse; + } - this.lut = lut; - this.inverse = inverse; + public float Calculate(float value) + { + if (this.inverse) + { + return this.LookupInverse(value); } - - public float Calculate(float value) + else { - if (this.inverse) - { - return this.LookupInverse(value); - } - else - { - return this.Lookup(value); - } + return this.Lookup(value); } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float Lookup(float value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float Lookup(float value) + { + float factor = value * (this.lut.Length - 1); + int index = (int)factor; + float low = this.lut[index]; + float high = this.lut[index + 1]; + return low + ((high - low) * (factor - index)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float LookupInverse(float value) + { + int index = Array.BinarySearch(this.lut, value); + if (index >= 0) { - float factor = value * (this.lut.Length - 1); - int index = (int)factor; - float low = this.lut[index]; - float high = this.lut[index + 1]; - return low + ((high - low) * (factor - index)); + return index / (float)(this.lut.Length - 1); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float LookupInverse(float value) + index = ~index; + if (index == 0) { - int index = Array.BinarySearch(this.lut, value); - if (index >= 0) - { - return index / (float)(this.lut.Length - 1); - } - - index = ~index; - if (index == 0) - { - return 0; - } - else if (index == this.lut.Length) - { - return 1; - } + return 0; + } + else if (index == this.lut.Length) + { + return 1; + } - float high = this.lut[index]; - float low = this.lut[index - 1]; + float high = this.lut[index]; + float low = this.lut[index - 1]; - float valuePercent = (value - low) / (high - low); - float lutRange = 1 / (float)(this.lut.Length - 1); - float lutLow = (index - 1) / (float)(this.lut.Length - 1); + float valuePercent = (value - low) / (high - low); + float lutRange = 1 / (float)(this.lut.Length - 1); + float lutLow = (index - 1) / (float)(this.lut.Length - 1); - return lutLow + (valuePercent * lutRange); - } + return lutLow + (valuePercent * lutRange); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutEntryCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutEntryCalculator.cs index 6005990cd..dd3e62a76 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutEntryCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutEntryCalculator.cs @@ -4,72 +4,71 @@ using System.Numerics; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal class LutEntryCalculator : IVector4Calculator { - internal class LutEntryCalculator : IVector4Calculator + private LutCalculator[] inputCurve; + private LutCalculator[] outputCurve; + private ClutCalculator clutCalculator; + private Matrix4x4 matrix; + private bool doTransform; + + public LutEntryCalculator(IccLut8TagDataEntry lut) { - private LutCalculator[] inputCurve; - private LutCalculator[] outputCurve; - private ClutCalculator clutCalculator; - private Matrix4x4 matrix; - private bool doTransform; + Guard.NotNull(lut, nameof(lut)); + this.Init(lut.InputValues, lut.OutputValues, lut.ClutValues, lut.Matrix); + } - public LutEntryCalculator(IccLut8TagDataEntry lut) - { - Guard.NotNull(lut, nameof(lut)); - this.Init(lut.InputValues, lut.OutputValues, lut.ClutValues, lut.Matrix); - } + public LutEntryCalculator(IccLut16TagDataEntry lut) + { + Guard.NotNull(lut, nameof(lut)); + this.Init(lut.InputValues, lut.OutputValues, lut.ClutValues, lut.Matrix); + } - public LutEntryCalculator(IccLut16TagDataEntry lut) + public Vector4 Calculate(Vector4 value) + { + if (this.doTransform) { - Guard.NotNull(lut, nameof(lut)); - this.Init(lut.InputValues, lut.OutputValues, lut.ClutValues, lut.Matrix); + value = Vector4.Transform(value, this.matrix); } - public Vector4 Calculate(Vector4 value) - { - if (this.doTransform) - { - value = Vector4.Transform(value, this.matrix); - } + value = this.CalculateLut(this.inputCurve, value); + value = this.clutCalculator.Calculate(value); + return this.CalculateLut(this.outputCurve, value); + } - value = this.CalculateLut(this.inputCurve, value); - value = this.clutCalculator.Calculate(value); - return this.CalculateLut(this.outputCurve, value); - } + private unsafe Vector4 CalculateLut(LutCalculator[] lut, Vector4 value) + { + value = Vector4.Clamp(value, Vector4.Zero, Vector4.One); - private unsafe Vector4 CalculateLut(LutCalculator[] lut, Vector4 value) + float* valuePointer = (float*)&value; + for (int i = 0; i < lut.Length; i++) { - value = Vector4.Clamp(value, Vector4.Zero, Vector4.One); - - float* valuePointer = (float*)&value; - for (int i = 0; i < lut.Length; i++) - { - valuePointer[i] = lut[i].Calculate(valuePointer[i]); - } - - return value; + valuePointer[i] = lut[i].Calculate(valuePointer[i]); } - private void Init(IccLut[] inputCurve, IccLut[] outputCurve, IccClut clut, Matrix4x4 matrix) - { - this.inputCurve = InitLut(inputCurve); - this.outputCurve = InitLut(outputCurve); - this.clutCalculator = new ClutCalculator(clut); - this.matrix = matrix; + return value; + } - this.doTransform = !matrix.IsIdentity && inputCurve.Length == 3; - } + private void Init(IccLut[] inputCurve, IccLut[] outputCurve, IccClut clut, Matrix4x4 matrix) + { + this.inputCurve = InitLut(inputCurve); + this.outputCurve = InitLut(outputCurve); + this.clutCalculator = new ClutCalculator(clut); + this.matrix = matrix; - private static LutCalculator[] InitLut(IccLut[] curves) - { - LutCalculator[] calculators = new LutCalculator[curves.Length]; - for (int i = 0; i < curves.Length; i++) - { - calculators[i] = new LutCalculator(curves[i].Values, false); - } + this.doTransform = !matrix.IsIdentity && inputCurve.Length == 3; + } - return calculators; + private static LutCalculator[] InitLut(IccLut[] curves) + { + LutCalculator[] calculators = new LutCalculator[curves.Length]; + for (int i = 0; i < curves.Length; i++) + { + calculators[i] = new LutCalculator(curves[i].Values, false); } + + return calculators; } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/MatrixCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/MatrixCalculator.cs index 570e02b81..f479d186a 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/MatrixCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/MatrixCalculator.cs @@ -4,24 +4,23 @@ using System.Numerics; using System.Runtime.CompilerServices; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal class MatrixCalculator : IVector4Calculator { - internal class MatrixCalculator : IVector4Calculator - { - private Matrix4x4 matrix2D; - private Vector4 matrix1D; + private Matrix4x4 matrix2D; + private Vector4 matrix1D; - public MatrixCalculator(Matrix4x4 matrix3x3, Vector3 matrix3x1) - { - this.matrix2D = matrix3x3; - this.matrix1D = new Vector4(matrix3x1, 0); - } + public MatrixCalculator(Matrix4x4 matrix3x3, Vector3 matrix3x1) + { + this.matrix2D = matrix3x3; + this.matrix1D = new Vector4(matrix3x1, 0); + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 Calculate(Vector4 value) - { - var transformed = Vector4.Transform(value, this.matrix2D); - return Vector4.Add(this.matrix1D, transformed); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 Calculate(Vector4 value) + { + var transformed = Vector4.Transform(value, this.matrix2D); + return Vector4.Add(this.matrix1D, transformed); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ParametricCurveCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ParametricCurveCalculator.cs index 53d783bb4..5a3bab6e8 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ParametricCurveCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ParametricCurveCalculator.cs @@ -5,164 +5,163 @@ using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal class ParametricCurveCalculator : ISingleCalculator { - internal class ParametricCurveCalculator : ISingleCalculator + private IccParametricCurve curve; + private IccParametricCurveType type; + private const IccParametricCurveType InvertedFlag = (IccParametricCurveType)(1 << 3); + + public ParametricCurveCalculator(IccParametricCurveTagDataEntry entry, bool inverted) { - private IccParametricCurve curve; - private IccParametricCurveType type; - private const IccParametricCurveType InvertedFlag = (IccParametricCurveType)(1 << 3); - - public ParametricCurveCalculator(IccParametricCurveTagDataEntry entry, bool inverted) - { - Guard.NotNull(entry, nameof(entry)); - this.curve = entry.Curve; - this.type = entry.Curve.Type; + Guard.NotNull(entry, nameof(entry)); + this.curve = entry.Curve; + this.type = entry.Curve.Type; - if (inverted) - { - this.type |= InvertedFlag; - } + if (inverted) + { + this.type |= InvertedFlag; } + } - public float Calculate(float value) + public float Calculate(float value) + { + switch (this.type) { - switch (this.type) - { - case IccParametricCurveType.Type1: - return this.CalculateGamma(value); - case IccParametricCurveType.Cie122_1996: - return this.CalculateCie122(value); - case IccParametricCurveType.Iec61966_3: - return this.CalculateIec61966(value); - case IccParametricCurveType.SRgb: - return this.CalculateSRgb(value); - case IccParametricCurveType.Type5: - return this.CalculateType5(value); + case IccParametricCurveType.Type1: + return this.CalculateGamma(value); + case IccParametricCurveType.Cie122_1996: + return this.CalculateCie122(value); + case IccParametricCurveType.Iec61966_3: + return this.CalculateIec61966(value); + case IccParametricCurveType.SRgb: + return this.CalculateSRgb(value); + case IccParametricCurveType.Type5: + return this.CalculateType5(value); + + case IccParametricCurveType.Type1 | InvertedFlag: + return this.CalculateInvertedGamma(value); + case IccParametricCurveType.Cie122_1996 | InvertedFlag: + return this.CalculateInvertedCie122(value); + case IccParametricCurveType.Iec61966_3 | InvertedFlag: + return this.CalculateInvertedIec61966(value); + case IccParametricCurveType.SRgb | InvertedFlag: + return this.CalculateInvertedSRgb(value); + case IccParametricCurveType.Type5 | InvertedFlag: + return this.CalculateInvertedType5(value); + + default: + throw new InvalidIccProfileException("ParametricCurve"); + } + } - case IccParametricCurveType.Type1 | InvertedFlag: - return this.CalculateInvertedGamma(value); - case IccParametricCurveType.Cie122_1996 | InvertedFlag: - return this.CalculateInvertedCie122(value); - case IccParametricCurveType.Iec61966_3 | InvertedFlag: - return this.CalculateInvertedIec61966(value); - case IccParametricCurveType.SRgb | InvertedFlag: - return this.CalculateInvertedSRgb(value); - case IccParametricCurveType.Type5 | InvertedFlag: - return this.CalculateInvertedType5(value); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateGamma(float value) + { + return MathF.Pow(value, this.curve.G); + } - default: - throw new InvalidIccProfileException("ParametricCurve"); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateCie122(float value) + { + if (value >= -this.curve.B / this.curve.A) + { + return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G); } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateGamma(float value) + else { - return MathF.Pow(value, this.curve.G); + return 0; } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateCie122(float value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateIec61966(float value) + { + if (value >= -this.curve.B / this.curve.A) { - if (value >= -this.curve.B / this.curve.A) - { - return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G); - } - else - { - return 0; - } + return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G) + this.curve.C; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateIec61966(float value) + else { - if (value >= -this.curve.B / this.curve.A) - { - return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G) + this.curve.C; - } - else - { - return this.curve.C; - } + return this.curve.C; } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateSRgb(float value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateSRgb(float value) + { + if (value >= this.curve.D) { - if (value >= this.curve.D) - { - return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G); - } - else - { - return this.curve.C * value; - } + return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G); } + else + { + return this.curve.C * value; + } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateType5(float value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateType5(float value) + { + if (value >= this.curve.D) + { + return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G) + this.curve.E; + } + else { - if (value >= this.curve.D) - { - return MathF.Pow((this.curve.A * value) + this.curve.B, this.curve.G) + this.curve.E; - } - else - { - return (this.curve.C * value) + this.curve.F; - } + return (this.curve.C * value) + this.curve.F; } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateInvertedGamma(float value) + { + return MathF.Pow(value, 1 / this.curve.G); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateInvertedCie122(float value) + { + return (MathF.Pow(value, 1 / this.curve.G) - this.curve.B) / this.curve.A; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateInvertedGamma(float value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateInvertedIec61966(float value) + { + if (value >= this.curve.C) + { + return (MathF.Pow(value - this.curve.C, 1 / this.curve.G) - this.curve.B) / this.curve.A; + } + else { - return MathF.Pow(value, 1 / this.curve.G); + return -this.curve.B / this.curve.A; } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateInvertedCie122(float value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateInvertedSRgb(float value) + { + if (value >= MathF.Pow((this.curve.A * this.curve.D) + this.curve.B, this.curve.G)) { return (MathF.Pow(value, 1 / this.curve.G) - this.curve.B) / this.curve.A; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateInvertedIec61966(float value) + else { - if (value >= this.curve.C) - { - return (MathF.Pow(value - this.curve.C, 1 / this.curve.G) - this.curve.B) / this.curve.A; - } - else - { - return -this.curve.B / this.curve.A; - } + return value / this.curve.C; } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateInvertedSRgb(float value) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private float CalculateInvertedType5(float value) + { + if (value >= (this.curve.C * this.curve.D) + this.curve.F) { - if (value >= MathF.Pow((this.curve.A * this.curve.D) + this.curve.B, this.curve.G)) - { - return (MathF.Pow(value, 1 / this.curve.G) - this.curve.B) / this.curve.A; - } - else - { - return value / this.curve.C; - } + return (MathF.Pow(value - this.curve.E, 1 / this.curve.G) - this.curve.B) / this.curve.A; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private float CalculateInvertedType5(float value) + else { - if (value >= (this.curve.C * this.curve.D) + this.curve.F) - { - return (MathF.Pow(value - this.curve.E, 1 / this.curve.G) - this.curve.B) / this.curve.A; - } - else - { - return (value - this.curve.F) / this.curve.C; - } + return (value - this.curve.F) / this.curve.C; } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/TrcCalculator.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/TrcCalculator.cs index 0a8042aa6..83a6f0ecd 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/TrcCalculator.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/TrcCalculator.cs @@ -4,44 +4,43 @@ using System.Numerics; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +internal class TrcCalculator : IVector4Calculator { - internal class TrcCalculator : IVector4Calculator + private ISingleCalculator[] calculators; + + public TrcCalculator(IccTagDataEntry[] entries, bool inverted) { - private ISingleCalculator[] calculators; + Guard.NotNull(entries, nameof(entries)); - public TrcCalculator(IccTagDataEntry[] entries, bool inverted) + this.calculators = new ISingleCalculator[entries.Length]; + for (int i = 0; i < entries.Length; i++) { - Guard.NotNull(entries, nameof(entries)); - - this.calculators = new ISingleCalculator[entries.Length]; - for (int i = 0; i < entries.Length; i++) + switch (entries[i]) { - switch (entries[i]) - { - case IccCurveTagDataEntry curve: - this.calculators[i] = new CurveCalculator(curve, inverted); - break; - - case IccParametricCurveTagDataEntry parametricCurve: - this.calculators[i] = new ParametricCurveCalculator(parametricCurve, inverted); - break; - - default: - throw new InvalidIccProfileException("Invalid Entry."); - } + case IccCurveTagDataEntry curve: + this.calculators[i] = new CurveCalculator(curve, inverted); + break; + + case IccParametricCurveTagDataEntry parametricCurve: + this.calculators[i] = new ParametricCurveCalculator(parametricCurve, inverted); + break; + + default: + throw new InvalidIccProfileException("Invalid Entry."); } } + } - public unsafe Vector4 Calculate(Vector4 value) + public unsafe Vector4 Calculate(Vector4 value) + { + float* valuePointer = (float*)&value; + for (int i = 0; i < this.calculators.Length; i++) { - float* valuePointer = (float*)&value; - for (int i = 0; i < this.calculators.Length; i++) - { - valuePointer[i] = this.calculators[i].Calculate(valuePointer[i]); - } - - return value; + valuePointer[i] = this.calculators[i].Calculate(valuePointer[i]); } + + return value; } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.ConversionMethod.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.ConversionMethod.cs index 4a74434cc..396756021 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.ConversionMethod.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.ConversionMethod.cs @@ -1,67 +1,66 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Color converter for ICC profiles +/// +internal abstract partial class IccConverterBase { /// - /// Color converter for ICC profiles + /// Conversion methods with ICC profiles /// - internal abstract partial class IccConverterBase + private enum ConversionMethod { /// - /// Conversion methods with ICC profiles + /// Conversion using anything but Multi Process Elements with perceptual rendering intent /// - private enum ConversionMethod - { - /// - /// Conversion using anything but Multi Process Elements with perceptual rendering intent - /// - A0, + A0, - /// - /// Conversion using anything but Multi Process Elements with relative colorimetric rendering intent - /// - A1, + /// + /// Conversion using anything but Multi Process Elements with relative colorimetric rendering intent + /// + A1, - /// - /// Conversion using anything but Multi Process Elements with saturation rendering intent - /// - A2, + /// + /// Conversion using anything but Multi Process Elements with saturation rendering intent + /// + A2, - /// - /// Conversion using Multi Process Elements with perceptual rendering intent - /// - D0, + /// + /// Conversion using Multi Process Elements with perceptual rendering intent + /// + D0, - /// - /// Conversion using Multi Process Elements with relative colorimetric rendering intent - /// - D1, + /// + /// Conversion using Multi Process Elements with relative colorimetric rendering intent + /// + D1, - /// - /// Conversion using Multi Process Elements with saturation rendering intent - /// - D2, + /// + /// Conversion using Multi Process Elements with saturation rendering intent + /// + D2, - /// - /// Conversion using Multi Process Elements with absolute colorimetric rendering intent - /// - D3, + /// + /// Conversion using Multi Process Elements with absolute colorimetric rendering intent + /// + D3, - /// - /// Conversion of more than one channel using tone reproduction curves - /// - ColorTrc, + /// + /// Conversion of more than one channel using tone reproduction curves + /// + ColorTrc, - /// - /// Conversion of exactly one channel using a tone reproduction curve - /// - GrayTrc, + /// + /// Conversion of exactly one channel using a tone reproduction curve + /// + GrayTrc, - /// - /// No valid conversion method available or found - /// - Invalid, - } + /// + /// No valid conversion method available or found + /// + Invalid, } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs index 6e4c58e18..56941c19e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs @@ -5,146 +5,145 @@ using System; using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Color converter for ICC profiles +/// +internal abstract partial class IccConverterBase { + private IVector4Calculator calculator; + /// - /// Color converter for ICC profiles + /// Checks the profile for available conversion methods and gathers all the informations necessary for it /// - internal abstract partial class IccConverterBase + /// The profile to use for the conversion + /// True if the conversion is to the Profile Connection Space + /// The wanted rendering intent. Can be ignored if not available + protected void Init(IccProfile profile, bool toPcs, IccRenderingIntent renderingIntent) { - private IVector4Calculator calculator; - - /// - /// Checks the profile for available conversion methods and gathers all the informations necessary for it - /// - /// The profile to use for the conversion - /// True if the conversion is to the Profile Connection Space - /// The wanted rendering intent. Can be ignored if not available - protected void Init(IccProfile profile, bool toPcs, IccRenderingIntent renderingIntent) + ConversionMethod method = GetConversionMethod(profile, renderingIntent); + switch (method) { - ConversionMethod method = GetConversionMethod(profile, renderingIntent); - switch (method) - { - case ConversionMethod.D0: - this.calculator = toPcs ? - InitD(profile, IccProfileTag.DToB0) : - InitD(profile, IccProfileTag.BToD0); - break; - - case ConversionMethod.D1: - this.calculator = toPcs ? - InitD(profile, IccProfileTag.DToB1) : - InitD(profile, IccProfileTag.BToD1); - break; - - case ConversionMethod.D2: - this.calculator = toPcs ? - InitD(profile, IccProfileTag.DToB2) : - InitD(profile, IccProfileTag.BToD2); - break; - - case ConversionMethod.D3: - this.calculator = toPcs ? - InitD(profile, IccProfileTag.DToB3) : - InitD(profile, IccProfileTag.BToD3); - break; - - case ConversionMethod.A0: - this.calculator = toPcs ? - InitA(profile, IccProfileTag.AToB0) : - InitA(profile, IccProfileTag.BToA0); - break; - - case ConversionMethod.A1: - this.calculator = toPcs ? - InitA(profile, IccProfileTag.AToB1) : - InitA(profile, IccProfileTag.BToA1); - break; - - case ConversionMethod.A2: - this.calculator = toPcs ? - InitA(profile, IccProfileTag.AToB2) : - InitA(profile, IccProfileTag.BToA2); - break; - - case ConversionMethod.ColorTrc: - this.calculator = InitColorTrc(profile, toPcs); - break; - - case ConversionMethod.GrayTrc: - this.calculator = InitGrayTrc(profile, toPcs); - break; - - case ConversionMethod.Invalid: - default: - throw new InvalidIccProfileException("Invalid conversion method."); - } + case ConversionMethod.D0: + this.calculator = toPcs ? + InitD(profile, IccProfileTag.DToB0) : + InitD(profile, IccProfileTag.BToD0); + break; + + case ConversionMethod.D1: + this.calculator = toPcs ? + InitD(profile, IccProfileTag.DToB1) : + InitD(profile, IccProfileTag.BToD1); + break; + + case ConversionMethod.D2: + this.calculator = toPcs ? + InitD(profile, IccProfileTag.DToB2) : + InitD(profile, IccProfileTag.BToD2); + break; + + case ConversionMethod.D3: + this.calculator = toPcs ? + InitD(profile, IccProfileTag.DToB3) : + InitD(profile, IccProfileTag.BToD3); + break; + + case ConversionMethod.A0: + this.calculator = toPcs ? + InitA(profile, IccProfileTag.AToB0) : + InitA(profile, IccProfileTag.BToA0); + break; + + case ConversionMethod.A1: + this.calculator = toPcs ? + InitA(profile, IccProfileTag.AToB1) : + InitA(profile, IccProfileTag.BToA1); + break; + + case ConversionMethod.A2: + this.calculator = toPcs ? + InitA(profile, IccProfileTag.AToB2) : + InitA(profile, IccProfileTag.BToA2); + break; + + case ConversionMethod.ColorTrc: + this.calculator = InitColorTrc(profile, toPcs); + break; + + case ConversionMethod.GrayTrc: + this.calculator = InitGrayTrc(profile, toPcs); + break; + + case ConversionMethod.Invalid: + default: + throw new InvalidIccProfileException("Invalid conversion method."); } + } - private static IVector4Calculator InitA(IccProfile profile, IccProfileTag tag) + private static IVector4Calculator InitA(IccProfile profile, IccProfileTag tag) + { + IccTagDataEntry entry = GetTag(profile, tag); + switch (entry) { - IccTagDataEntry entry = GetTag(profile, tag); - switch (entry) - { - case IccLut8TagDataEntry lut8: - return new LutEntryCalculator(lut8); - case IccLut16TagDataEntry lut16: - return new LutEntryCalculator(lut16); - case IccLutAToBTagDataEntry lutAtoB: - return new LutABCalculator(lutAtoB); - case IccLutBToATagDataEntry lutBtoA: - return new LutABCalculator(lutBtoA); - - default: - throw new InvalidIccProfileException("Invalid entry."); - } + case IccLut8TagDataEntry lut8: + return new LutEntryCalculator(lut8); + case IccLut16TagDataEntry lut16: + return new LutEntryCalculator(lut16); + case IccLutAToBTagDataEntry lutAtoB: + return new LutABCalculator(lutAtoB); + case IccLutBToATagDataEntry lutBtoA: + return new LutABCalculator(lutBtoA); + + default: + throw new InvalidIccProfileException("Invalid entry."); } + } - private static IVector4Calculator InitD(IccProfile profile, IccProfileTag tag) + private static IVector4Calculator InitD(IccProfile profile, IccProfileTag tag) + { + IccMultiProcessElementsTagDataEntry entry = GetTag(profile, tag); + if (entry == null) { - IccMultiProcessElementsTagDataEntry entry = GetTag(profile, tag); - if (entry == null) - { - throw new InvalidIccProfileException("Entry is null."); - } - - throw new NotImplementedException("Multi process elements are not supported"); + throw new InvalidIccProfileException("Entry is null."); } - private static IVector4Calculator InitColorTrc(IccProfile profile, bool toPcs) - { - IccXyzTagDataEntry redMatrixColumn = GetTag(profile, IccProfileTag.RedMatrixColumn); - IccXyzTagDataEntry greenMatrixColumn = GetTag(profile, IccProfileTag.GreenMatrixColumn); - IccXyzTagDataEntry blueMatrixColumn = GetTag(profile, IccProfileTag.BlueMatrixColumn); - - IccTagDataEntry redTrc = GetTag(profile, IccProfileTag.RedTrc); - IccTagDataEntry greenTrc = GetTag(profile, IccProfileTag.GreenTrc); - IccTagDataEntry blueTrc = GetTag(profile, IccProfileTag.BlueTrc); - - if (redMatrixColumn == null || - greenMatrixColumn == null || - blueMatrixColumn == null || - redTrc == null || - greenTrc == null || - blueTrc == null) - { - throw new InvalidIccProfileException("Missing matrix column or channel."); - } - - return new ColorTrcCalculator( - redMatrixColumn, - greenMatrixColumn, - blueMatrixColumn, - redTrc, - greenTrc, - blueTrc, - toPcs); - } + throw new NotImplementedException("Multi process elements are not supported"); + } - private static IVector4Calculator InitGrayTrc(IccProfile profile, bool toPcs) + private static IVector4Calculator InitColorTrc(IccProfile profile, bool toPcs) + { + IccXyzTagDataEntry redMatrixColumn = GetTag(profile, IccProfileTag.RedMatrixColumn); + IccXyzTagDataEntry greenMatrixColumn = GetTag(profile, IccProfileTag.GreenMatrixColumn); + IccXyzTagDataEntry blueMatrixColumn = GetTag(profile, IccProfileTag.BlueMatrixColumn); + + IccTagDataEntry redTrc = GetTag(profile, IccProfileTag.RedTrc); + IccTagDataEntry greenTrc = GetTag(profile, IccProfileTag.GreenTrc); + IccTagDataEntry blueTrc = GetTag(profile, IccProfileTag.BlueTrc); + + if (redMatrixColumn == null || + greenMatrixColumn == null || + blueMatrixColumn == null || + redTrc == null || + greenTrc == null || + blueTrc == null) { - IccTagDataEntry entry = GetTag(profile, IccProfileTag.GrayTrc); - return new GrayTrcCalculator(entry, toPcs); + throw new InvalidIccProfileException("Missing matrix column or channel."); } + + return new ColorTrcCalculator( + redMatrixColumn, + greenMatrixColumn, + blueMatrixColumn, + redTrc, + greenTrc, + blueTrc, + toPcs); + } + + private static IVector4Calculator InitGrayTrc(IccProfile profile, bool toPcs) + { + IccTagDataEntry entry = GetTag(profile, IccProfileTag.GrayTrc); + return new GrayTrcCalculator(entry, toPcs); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.cs index d0e147c19..6e9c8aa82 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.cs @@ -5,33 +5,32 @@ using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Color converter for ICC profiles +/// +internal abstract partial class IccConverterBase { /// - /// Color converter for ICC profiles + /// Initializes a new instance of the class. /// - internal abstract partial class IccConverterBase + /// The ICC profile to use for the conversions + /// True if the conversion is to the profile connection space (PCS); False if the conversion is to the data space + protected IccConverterBase(IccProfile profile, bool toPcs) { - /// - /// Initializes a new instance of the class. - /// - /// The ICC profile to use for the conversions - /// True if the conversion is to the profile connection space (PCS); False if the conversion is to the data space - protected IccConverterBase(IccProfile profile, bool toPcs) - { - Guard.NotNull(profile, nameof(profile)); - this.Init(profile, toPcs, profile.Header.RenderingIntent); - } + Guard.NotNull(profile, nameof(profile)); + this.Init(profile, toPcs, profile.Header.RenderingIntent); + } - /// - /// Converts colors with the initially provided ICC profile - /// - /// The value to convert - /// The converted value - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 Calculate(Vector4 value) - { - return this.calculator.Calculate(value); - } + /// + /// Converts colors with the initially provided ICC profile + /// + /// The value to convert + /// The converted value + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Vector4 Calculate(Vector4 value) + { + return this.calculator.Calculate(value); } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToDataConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToDataConverter.cs index dccba51cc..86e73b54d 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToDataConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToDataConverter.cs @@ -3,20 +3,19 @@ using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Color converter for ICC profiles +/// +internal class IccDataToDataConverter : IccConverterBase { /// - /// Color converter for ICC profiles + /// Initializes a new instance of the class. /// - internal class IccDataToDataConverter : IccConverterBase + /// The ICC profile to use for the conversions + public IccDataToDataConverter(IccProfile profile) + : base(profile, true) // toPCS is true because in this case the PCS space is also a data space { - /// - /// Initializes a new instance of the class. - /// - /// The ICC profile to use for the conversions - public IccDataToDataConverter(IccProfile profile) - : base(profile, true) // toPCS is true because in this case the PCS space is also a data space - { - } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToPcsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToPcsConverter.cs index 6cec8695f..86ed81240 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToPcsConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToPcsConverter.cs @@ -3,20 +3,19 @@ using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Color converter for ICC profiles +/// +internal class IccDataToPcsConverter : IccConverterBase { /// - /// Color converter for ICC profiles + /// Initializes a new instance of the class. /// - internal class IccDataToPcsConverter : IccConverterBase + /// The ICC profile to use for the conversions + public IccDataToPcsConverter(IccProfile profile) + : base(profile, true) { - /// - /// Initializes a new instance of the class. - /// - /// The ICC profile to use for the conversions - public IccDataToPcsConverter(IccProfile profile) - : base(profile, true) - { - } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToDataConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToDataConverter.cs index 5647c465c..c38f7b64e 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToDataConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToDataConverter.cs @@ -3,20 +3,19 @@ using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Color converter for ICC profiles +/// +internal class IccPcsToDataConverter : IccConverterBase { /// - /// Color converter for ICC profiles + /// Initializes a new instance of the class. /// - internal class IccPcsToDataConverter : IccConverterBase + /// The ICC profile to use for the conversions + public IccPcsToDataConverter(IccProfile profile) + : base(profile, false) { - /// - /// Initializes a new instance of the class. - /// - /// The ICC profile to use for the conversions - public IccPcsToDataConverter(IccProfile profile) - : base(profile, false) - { - } } } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToPcsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToPcsConverter.cs index a40a81d5d..7d85203df 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToPcsConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToPcsConverter.cs @@ -3,20 +3,19 @@ using SixLabors.ImageSharp.Metadata.Profiles.Icc; -namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc +namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; + +/// +/// Color converter for ICC profiles +/// +internal class IccPcsToPcsConverter : IccConverterBase { /// - /// Color converter for ICC profiles + /// Initializes a new instance of the class. /// - internal class IccPcsToPcsConverter : IccConverterBase + /// The ICC profile to use for the conversions + public IccPcsToPcsConverter(IccProfile profile) + : base(profile, true) { - /// - /// Initializes a new instance of the class. - /// - /// The ICC profile to use for the conversions - public IccPcsToPcsConverter(IccProfile profile) - : base(profile, true) - { - } } }