Browse Source

Use file scoped namespaces

pull/1567/head
Brian Popow 3 years ago
parent
commit
0a08da0bc6
  1. 17
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.CalculationType.cs
  2. 70
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.cs
  3. 25
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/GrayTrcCalculator.cs
  4. 21
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ISingleCalculator.cs
  5. 21
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/IVector4Calculator.cs
  6. 21
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.CalculationType.cs
  7. 225
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs
  8. 99
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs
  9. 101
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutEntryCalculator.cs
  10. 31
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/MatrixCalculator.cs
  11. 245
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ParametricCurveCalculator.cs
  12. 57
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/TrcCalculator.cs
  13. 93
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.ConversionMethod.cs
  14. 249
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs
  15. 45
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.cs
  16. 21
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToDataConverter.cs
  17. 21
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToPcsConverter.cs
  18. 21
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToDataConverter.cs
  19. 21
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToPcsConverter.cs

17
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,
}
}

70
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");
}
}
}

25
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);
}
}

21
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;
/// <summary>
/// Represents an ICC calculator with a single floating point value and result
/// </summary>
internal interface ISingleCalculator
{
/// <summary>
/// Represents an ICC calculator with a single floating point value and result
/// Calculates a result from the given value
/// </summary>
internal interface ISingleCalculator
{
/// <summary>
/// Calculates a result from the given value
/// </summary>
/// <param name="value">The input value</param>
/// <returns>The calculated result</returns>
float Calculate(float value);
}
/// <param name="value">The input value</param>
/// <returns>The calculated result</returns>
float Calculate(float value);
}

21
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;
/// <summary>
/// Represents an ICC calculator with <see cref="Vector4"/> values and results
/// </summary>
internal interface IVector4Calculator
{
/// <summary>
/// Represents an ICC calculator with <see cref="Vector4"/> values and results
/// Calculates a result from the given values
/// </summary>
internal interface IVector4Calculator
{
/// <summary>
/// Calculates a result from the given values
/// </summary>
/// <param name="value">The input values</param>
/// <returns>The calculated result</returns>
Vector4 Calculate(Vector4 value);
}
/// <param name="value">The input values</param>
/// <returns>The calculated result</returns>
Vector4 Calculate(Vector4 value);
}

21
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,
}
}

225
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);
}
}
}

99
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);
}
}

101
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;
}
}

31
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);
}
}

245
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;
}
}
}

57
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;
}
}

93
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;
/// <summary>
/// Color converter for ICC profiles
/// </summary>
internal abstract partial class IccConverterBase
{
/// <summary>
/// Color converter for ICC profiles
/// Conversion methods with ICC profiles
/// </summary>
internal abstract partial class IccConverterBase
private enum ConversionMethod
{
/// <summary>
/// Conversion methods with ICC profiles
/// Conversion using anything but Multi Process Elements with perceptual rendering intent
/// </summary>
private enum ConversionMethod
{
/// <summary>
/// Conversion using anything but Multi Process Elements with perceptual rendering intent
/// </summary>
A0,
A0,
/// <summary>
/// Conversion using anything but Multi Process Elements with relative colorimetric rendering intent
/// </summary>
A1,
/// <summary>
/// Conversion using anything but Multi Process Elements with relative colorimetric rendering intent
/// </summary>
A1,
/// <summary>
/// Conversion using anything but Multi Process Elements with saturation rendering intent
/// </summary>
A2,
/// <summary>
/// Conversion using anything but Multi Process Elements with saturation rendering intent
/// </summary>
A2,
/// <summary>
/// Conversion using Multi Process Elements with perceptual rendering intent
/// </summary>
D0,
/// <summary>
/// Conversion using Multi Process Elements with perceptual rendering intent
/// </summary>
D0,
/// <summary>
/// Conversion using Multi Process Elements with relative colorimetric rendering intent
/// </summary>
D1,
/// <summary>
/// Conversion using Multi Process Elements with relative colorimetric rendering intent
/// </summary>
D1,
/// <summary>
/// Conversion using Multi Process Elements with saturation rendering intent
/// </summary>
D2,
/// <summary>
/// Conversion using Multi Process Elements with saturation rendering intent
/// </summary>
D2,
/// <summary>
/// Conversion using Multi Process Elements with absolute colorimetric rendering intent
/// </summary>
D3,
/// <summary>
/// Conversion using Multi Process Elements with absolute colorimetric rendering intent
/// </summary>
D3,
/// <summary>
/// Conversion of more than one channel using tone reproduction curves
/// </summary>
ColorTrc,
/// <summary>
/// Conversion of more than one channel using tone reproduction curves
/// </summary>
ColorTrc,
/// <summary>
/// Conversion of exactly one channel using a tone reproduction curve
/// </summary>
GrayTrc,
/// <summary>
/// Conversion of exactly one channel using a tone reproduction curve
/// </summary>
GrayTrc,
/// <summary>
/// No valid conversion method available or found
/// </summary>
Invalid,
}
/// <summary>
/// No valid conversion method available or found
/// </summary>
Invalid,
}
}

249
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;
/// <summary>
/// Color converter for ICC profiles
/// </summary>
internal abstract partial class IccConverterBase
{
private IVector4Calculator calculator;
/// <summary>
/// Color converter for ICC profiles
/// Checks the profile for available conversion methods and gathers all the informations necessary for it
/// </summary>
internal abstract partial class IccConverterBase
/// <param name="profile">The profile to use for the conversion</param>
/// <param name="toPcs">True if the conversion is to the Profile Connection Space</param>
/// <param name="renderingIntent">The wanted rendering intent. Can be ignored if not available</param>
protected void Init(IccProfile profile, bool toPcs, IccRenderingIntent renderingIntent)
{
private IVector4Calculator calculator;
/// <summary>
/// Checks the profile for available conversion methods and gathers all the informations necessary for it
/// </summary>
/// <param name="profile">The profile to use for the conversion</param>
/// <param name="toPcs">True if the conversion is to the Profile Connection Space</param>
/// <param name="renderingIntent">The wanted rendering intent. Can be ignored if not available</param>
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<IccMultiProcessElementsTagDataEntry>(profile, tag);
if (entry == null)
{
IccMultiProcessElementsTagDataEntry entry = GetTag<IccMultiProcessElementsTagDataEntry>(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<IccXyzTagDataEntry>(profile, IccProfileTag.RedMatrixColumn);
IccXyzTagDataEntry greenMatrixColumn = GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.GreenMatrixColumn);
IccXyzTagDataEntry blueMatrixColumn = GetTag<IccXyzTagDataEntry>(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<IccXyzTagDataEntry>(profile, IccProfileTag.RedMatrixColumn);
IccXyzTagDataEntry greenMatrixColumn = GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.GreenMatrixColumn);
IccXyzTagDataEntry blueMatrixColumn = GetTag<IccXyzTagDataEntry>(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);
}
}

45
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;
/// <summary>
/// Color converter for ICC profiles
/// </summary>
internal abstract partial class IccConverterBase
{
/// <summary>
/// Color converter for ICC profiles
/// Initializes a new instance of the <see cref="IccConverterBase"/> class.
/// </summary>
internal abstract partial class IccConverterBase
/// <param name="profile">The ICC profile to use for the conversions</param>
/// <param name="toPcs">True if the conversion is to the profile connection space (PCS); False if the conversion is to the data space</param>
protected IccConverterBase(IccProfile profile, bool toPcs)
{
/// <summary>
/// Initializes a new instance of the <see cref="IccConverterBase"/> class.
/// </summary>
/// <param name="profile">The ICC profile to use for the conversions</param>
/// <param name="toPcs">True if the conversion is to the profile connection space (PCS); False if the conversion is to the data space</param>
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);
}
/// <summary>
/// Converts colors with the initially provided ICC profile
/// </summary>
/// <param name="value">The value to convert</param>
/// <returns>The converted value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 Calculate(Vector4 value)
{
return this.calculator.Calculate(value);
}
/// <summary>
/// Converts colors with the initially provided ICC profile
/// </summary>
/// <param name="value">The value to convert</param>
/// <returns>The converted value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 Calculate(Vector4 value)
{
return this.calculator.Calculate(value);
}
}

21
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;
/// <summary>
/// Color converter for ICC profiles
/// </summary>
internal class IccDataToDataConverter : IccConverterBase
{
/// <summary>
/// Color converter for ICC profiles
/// Initializes a new instance of the <see cref="IccDataToDataConverter"/> class.
/// </summary>
internal class IccDataToDataConverter : IccConverterBase
/// <param name="profile">The ICC profile to use for the conversions</param>
public IccDataToDataConverter(IccProfile profile)
: base(profile, true) // toPCS is true because in this case the PCS space is also a data space
{
/// <summary>
/// Initializes a new instance of the <see cref="IccDataToDataConverter"/> class.
/// </summary>
/// <param name="profile">The ICC profile to use for the conversions</param>
public IccDataToDataConverter(IccProfile profile)
: base(profile, true) // toPCS is true because in this case the PCS space is also a data space
{
}
}
}

21
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;
/// <summary>
/// Color converter for ICC profiles
/// </summary>
internal class IccDataToPcsConverter : IccConverterBase
{
/// <summary>
/// Color converter for ICC profiles
/// Initializes a new instance of the <see cref="IccDataToPcsConverter"/> class.
/// </summary>
internal class IccDataToPcsConverter : IccConverterBase
/// <param name="profile">The ICC profile to use for the conversions</param>
public IccDataToPcsConverter(IccProfile profile)
: base(profile, true)
{
/// <summary>
/// Initializes a new instance of the <see cref="IccDataToPcsConverter"/> class.
/// </summary>
/// <param name="profile">The ICC profile to use for the conversions</param>
public IccDataToPcsConverter(IccProfile profile)
: base(profile, true)
{
}
}
}

21
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;
/// <summary>
/// Color converter for ICC profiles
/// </summary>
internal class IccPcsToDataConverter : IccConverterBase
{
/// <summary>
/// Color converter for ICC profiles
/// Initializes a new instance of the <see cref="IccPcsToDataConverter"/> class.
/// </summary>
internal class IccPcsToDataConverter : IccConverterBase
/// <param name="profile">The ICC profile to use for the conversions</param>
public IccPcsToDataConverter(IccProfile profile)
: base(profile, false)
{
/// <summary>
/// Initializes a new instance of the <see cref="IccPcsToDataConverter"/> class.
/// </summary>
/// <param name="profile">The ICC profile to use for the conversions</param>
public IccPcsToDataConverter(IccProfile profile)
: base(profile, false)
{
}
}
}

21
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;
/// <summary>
/// Color converter for ICC profiles
/// </summary>
internal class IccPcsToPcsConverter : IccConverterBase
{
/// <summary>
/// Color converter for ICC profiles
/// Initializes a new instance of the <see cref="IccPcsToPcsConverter"/> class.
/// </summary>
internal class IccPcsToPcsConverter : IccConverterBase
/// <param name="profile">The ICC profile to use for the conversions</param>
public IccPcsToPcsConverter(IccProfile profile)
: base(profile, true)
{
/// <summary>
/// Initializes a new instance of the <see cref="IccPcsToPcsConverter"/> class.
/// </summary>
/// <param name="profile">The ICC profile to use for the conversions</param>
public IccPcsToPcsConverter(IccProfile profile)
: base(profile, true)
{
}
}
}

Loading…
Cancel
Save