Browse Source

Fix build

pull/1567/head
James Jackson-South 4 years ago
parent
commit
dc166a7804
  1. 146
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ClutCalculator.cs
  2. 75
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ColorTrcCalculator.cs
  3. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.CalculationType.cs
  4. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.cs
  5. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/GrayTrcCalculator.cs
  6. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ISingleCalculator.cs
  7. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/IVector4Calculator.cs
  8. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.CalculationType.cs
  9. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs
  10. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs
  11. 10
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutEntryCalculator.cs
  12. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/MatrixCalculator.cs
  13. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ParametricCurveCalculator.cs
  14. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/TrcCalculator.cs
  15. 244
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.Checks.cs
  16. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.ConversionMethod.cs
  17. 62
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs
  18. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.cs
  19. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToDataConverter.cs
  20. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToPcsConverter.cs
  21. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToDataConverter.cs
  22. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToPcsConverter.cs
  23. 30
      tests/ImageSharp.Tests/Colorspaces/Icc/Calculators/ClutCalculatorTests.cs

146
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ClutCalculator.cs

@ -1,104 +1,102 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System;
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
internal class ClutCalculator : IVector4Calculator
{ {
internal class ClutCalculator : IVector4Calculator private readonly int inputCount;
private readonly int outputCount;
private readonly float[][] lut;
private readonly byte[] gridPointCount;
private readonly int[] indexFactor;
private readonly int nodeCount;
public ClutCalculator(IccClut clut)
{ {
private int inputCount; Guard.NotNull(clut, nameof(clut));
private int outputCount;
private float[][] lut; this.inputCount = clut.InputChannelCount;
private byte[] gridPointCount; this.outputCount = clut.OutputChannelCount;
private int[] indexFactor; this.lut = clut.Values;
private int nodeCount; this.gridPointCount = clut.GridPointCount;
this.indexFactor = CalculateIndexFactor(clut.InputChannelCount, clut.GridPointCount);
public ClutCalculator(IccClut clut) this.nodeCount = (int)Math.Pow(2, clut.InputChannelCount);
{ }
Guard.NotNull(clut, nameof(clut));
this.inputCount = clut.InputChannelCount;
this.outputCount = clut.OutputChannelCount;
this.lut = clut.Values;
this.gridPointCount = clut.GridPointCount;
this.indexFactor = this.CalculateIndexFactor(clut.InputChannelCount, clut.GridPointCount);
this.nodeCount = (int)Math.Pow(2, clut.InputChannelCount);
}
public unsafe Vector4 Calculate(Vector4 value) public unsafe Vector4 Calculate(Vector4 value)
{ {
value = Vector4.Clamp(value, Vector4.Zero, Vector4.One); value = Vector4.Clamp(value, Vector4.Zero, Vector4.One);
Vector4 result = default; Vector4 result = default;
this.Interpolate((float*)&value, this.inputCount, (float*)&result, this.outputCount); this.Interpolate((float*)&value, this.inputCount, (float*)&result, this.outputCount);
return result; return result;
}
private static int[] CalculateIndexFactor(int inputCount, byte[] gridPointCount)
{
int[] factors = new int[inputCount];
int gpc = 1;
for (int j = inputCount - 1; j >= 0; j--)
{
factors[j] = gpc * (gridPointCount[j] - 1);
gpc *= gridPointCount[j];
} }
private int[] CalculateIndexFactor(int inputCount, byte[] gridPointCount) return factors;
}
private unsafe void Interpolate(float* values, int valueLength, float* result, int resultLength)
{
float[][] nodes = new float[this.nodeCount][];
for (int i = 0; i < nodes.Length; i++)
{ {
int[] factors = new int[inputCount]; int index = 0;
int gpc = 1; for (int j = 0; j < valueLength; j++)
for (int j = inputCount - 1; j >= 0; j--)
{ {
factors[j] = gpc * (gridPointCount[j] - 1); float fraction = 1f / (this.gridPointCount[j] - 1);
gpc *= gridPointCount[j]; int position = (int)(values[j] / fraction) + ((i >> j) & 1);
index += (int)((this.indexFactor[j] * (position * fraction)) + 0.5f);
} }
return factors; nodes[i] = this.lut[index];
} }
private unsafe void Interpolate(float* values, int valueLength, float* result, int resultLength) Span<float> factors = stackalloc float[this.nodeCount];
for (int i = 0; i < factors.Length; i++)
{ {
float[][] nodes = new float[this.nodeCount][]; float factor = 1;
for (int i = 0; i < nodes.Length; i++) for (int j = 0; j < valueLength; j++)
{ {
int index = 0; float fraction = 1f / (this.gridPointCount[j] - 1);
for (int j = 0; j < valueLength; j++) int position = (int)(values[j] / fraction);
{
float fraction = 1f / (this.gridPointCount[j] - 1);
int position = (int)(values[j] / fraction) + ((i >> j) & 1);
index += (int)((this.indexFactor[j] * (position * fraction)) + 0.5f);
}
nodes[i] = this.lut[index]; float low = position * fraction;
} float high = (position + 1) * fraction;
float percentage = (high - values[j]) / (high - low);
Span<float> factors = stackalloc float[this.nodeCount]; if (((i >> j) & 1) == 1)
for (int i = 0; i < factors.Length; i++)
{
float factor = 1;
for (int j = 0; j < valueLength; j++)
{ {
float fraction = 1f / (this.gridPointCount[j] - 1); factor *= percentage;
int position = (int)(values[j] / fraction); }
else
float low = position * fraction; {
float high = (position + 1) * fraction; factor *= 1 - percentage;
float percentage = (high - values[j]) / (high - low);
if (((i >> j) & 1) == 1)
{
factor *= percentage;
}
else
{
factor *= 1 - percentage;
}
} }
factors[i] = factor;
} }
for (int i = 0; i < resultLength; i++) factors[i] = factor;
}
for (int i = 0; i < resultLength; i++)
{
for (int j = 0; j < nodes.Length; j++)
{ {
for (int j = 0; j < nodes.Length; j++) result[i] += nodes[j][i] * factors[j];
{
result[i] += nodes[j][i] * factors[j];
}
} }
} }
} }

75
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ColorTrcCalculator.cs

@ -1,54 +1,53 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
internal class ColorTrcCalculator : IVector4Calculator
{ {
internal class ColorTrcCalculator : IVector4Calculator private TrcCalculator curveCalculator;
{ private Matrix4x4 matrix;
private TrcCalculator curveCalculator; private bool toPcs;
private Matrix4x4 matrix;
private bool toPcs;
public ColorTrcCalculator( public ColorTrcCalculator(
IccXyzTagDataEntry redMatrixColumn, IccXyzTagDataEntry redMatrixColumn,
IccXyzTagDataEntry greenMatrixColumn, IccXyzTagDataEntry greenMatrixColumn,
IccXyzTagDataEntry blueMatrixColumn, IccXyzTagDataEntry blueMatrixColumn,
IccTagDataEntry redTrc, IccTagDataEntry redTrc,
IccTagDataEntry greenTrc, IccTagDataEntry greenTrc,
IccTagDataEntry blueTrc, IccTagDataEntry blueTrc,
bool toPcs) bool toPcs)
{ {
this.toPcs = toPcs; this.toPcs = toPcs;
this.curveCalculator = new TrcCalculator(new IccTagDataEntry[] { redTrc, greenTrc, blueTrc }, !toPcs); this.curveCalculator = new TrcCalculator(new IccTagDataEntry[] { redTrc, greenTrc, blueTrc }, !toPcs);
Vector3 mr = redMatrixColumn.Data[0]; Vector3 mr = redMatrixColumn.Data[0];
Vector3 mg = greenMatrixColumn.Data[0]; Vector3 mg = greenMatrixColumn.Data[0];
Vector3 mb = blueMatrixColumn.Data[0]; Vector3 mb = blueMatrixColumn.Data[0];
this.matrix = new Matrix4x4(mr.X, mr.Y, mr.Z, 0, mg.X, mg.Y, mg.Z, 0, mb.X, mb.Y, mb.Z, 0, 0, 0, 0, 1); this.matrix = new Matrix4x4(mr.X, mr.Y, mr.Z, 0, mg.X, mg.Y, mg.Z, 0, mb.X, mb.Y, mb.Z, 0, 0, 0, 0, 1);
if (!toPcs) if (!toPcs)
{ {
Matrix4x4.Invert(this.matrix, out this.matrix); Matrix4x4.Invert(this.matrix, out this.matrix);
}
} }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 Calculate(Vector4 value) public Vector4 Calculate(Vector4 value)
{
if (this.toPcs)
{
value = this.curveCalculator.Calculate(value);
return Vector4.Transform(value, this.matrix);
}
else
{ {
if (this.toPcs) value = Vector4.Transform(value, this.matrix);
{ return this.curveCalculator.Calculate(value);
value = this.curveCalculator.Calculate(value);
return Vector4.Transform(value, this.matrix);
}
else
{
value = Vector4.Transform(value, this.matrix);
return this.curveCalculator.Calculate(value);
}
} }
} }
} }

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.CalculationType.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
{ {

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/CurveCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System; using System;
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/GrayTrcCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ISingleCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
{ {

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/IVector4Calculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Numerics; using System.Numerics;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.CalculationType.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
{ {

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutABCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System; using System;
using System.Numerics; using System.Numerics;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

10
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/LutEntryCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;
@ -53,17 +53,17 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
private void Init(IccLut[] inputCurve, IccLut[] outputCurve, IccClut clut, Matrix4x4 matrix) private void Init(IccLut[] inputCurve, IccLut[] outputCurve, IccClut clut, Matrix4x4 matrix)
{ {
this.inputCurve = this.InitLut(inputCurve); this.inputCurve = InitLut(inputCurve);
this.outputCurve = this.InitLut(outputCurve); this.outputCurve = InitLut(outputCurve);
this.clutCalculator = new ClutCalculator(clut); this.clutCalculator = new ClutCalculator(clut);
this.matrix = matrix; this.matrix = matrix;
this.doTransform = !matrix.IsIdentity && inputCurve.Length == 3; this.doTransform = !matrix.IsIdentity && inputCurve.Length == 3;
} }
private LutCalculator[] InitLut(IccLut[] curves) private static LutCalculator[] InitLut(IccLut[] curves)
{ {
var calculators = new LutCalculator[curves.Length]; LutCalculator[] calculators = new LutCalculator[curves.Length];
for (int i = 0; i < curves.Length; i++) for (int i = 0; i < curves.Length; i++)
{ {
calculators[i] = new LutCalculator(curves[i].Values, false); calculators[i] = new LutCalculator(curves[i].Values, false);

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/MatrixCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/ParametricCurveCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/Calculators/TrcCalculator.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;

244
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.Checks.cs

@ -1,173 +1,165 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Linq;
using SixLabors.ImageSharp.Metadata.Profiles.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
{ {
/// <summary> private static ConversionMethod GetConversionMethod(IccProfile profile, IccRenderingIntent renderingIntent)
/// Color converter for ICC profiles
/// </summary>
internal abstract partial class IccConverterBase
{ {
private ConversionMethod GetConversionMethod(IccProfile profile, IccRenderingIntent renderingIntent) switch (profile.Header.Class)
{ {
switch (profile.Header.Class) case IccProfileClass.InputDevice:
{ case IccProfileClass.DisplayDevice:
case IccProfileClass.InputDevice: case IccProfileClass.OutputDevice:
case IccProfileClass.DisplayDevice: case IccProfileClass.ColorSpace:
case IccProfileClass.OutputDevice: return CheckMethod1(profile, renderingIntent);
case IccProfileClass.ColorSpace:
return this.CheckMethod1(profile, renderingIntent); case IccProfileClass.DeviceLink:
case IccProfileClass.Abstract:
return CheckMethod2(profile);
default:
return ConversionMethod.Invalid;
}
}
case IccProfileClass.DeviceLink: private static ConversionMethod CheckMethod1(IccProfile profile, IccRenderingIntent renderingIntent)
case IccProfileClass.Abstract: {
return this.CheckMethod2(profile); ConversionMethod method = ConversionMethod.Invalid;
default: method = CheckMethodD(profile, renderingIntent);
return ConversionMethod.Invalid; if (method != ConversionMethod.Invalid)
} {
return method;
} }
private ConversionMethod CheckMethod1(IccProfile profile, IccRenderingIntent renderingIntent) method = CheckMethodA(profile, renderingIntent);
if (method != ConversionMethod.Invalid)
{ {
ConversionMethod method = ConversionMethod.Invalid; return method;
method = this.CheckMethodD(profile, renderingIntent);
if (method != ConversionMethod.Invalid)
{
return method;
}
method = this.CheckMethodA(profile, renderingIntent);
if (method != ConversionMethod.Invalid)
{
return method;
}
method = this.CheckMethodA0(profile);
if (method != ConversionMethod.Invalid)
{
return method;
}
method = this.CheckMethodTrc(profile);
if (method != ConversionMethod.Invalid)
{
return method;
}
return ConversionMethod.Invalid;
} }
private ConversionMethod CheckMethodD(IccProfile profile, IccRenderingIntent renderingIntent) method = CheckMethodA0(profile);
if (method != ConversionMethod.Invalid)
{ {
if ((this.HasTag(profile, IccProfileTag.DToB0) || this.HasTag(profile, IccProfileTag.BToD0)) return method;
&& renderingIntent == IccRenderingIntent.Perceptual) }
{
return ConversionMethod.D0;
}
if ((this.HasTag(profile, IccProfileTag.DToB1) || this.HasTag(profile, IccProfileTag.BToD1)) method = CheckMethodTrc(profile);
&& renderingIntent == IccRenderingIntent.MediaRelativeColorimetric) if (method != ConversionMethod.Invalid)
{ {
return ConversionMethod.D1; return method;
} }
if ((this.HasTag(profile, IccProfileTag.DToB2) || this.HasTag(profile, IccProfileTag.BToD2)) return ConversionMethod.Invalid;
&& renderingIntent == IccRenderingIntent.Saturation) }
{
return ConversionMethod.D2;
}
if ((this.HasTag(profile, IccProfileTag.DToB3) || this.HasTag(profile, IccProfileTag.BToD3)) private static ConversionMethod CheckMethodD(IccProfile profile, IccRenderingIntent renderingIntent)
&& renderingIntent == IccRenderingIntent.AbsoluteColorimetric) {
{ if ((HasTag(profile, IccProfileTag.DToB0) || HasTag(profile, IccProfileTag.BToD0))
return ConversionMethod.D3; && renderingIntent == IccRenderingIntent.Perceptual)
} {
return ConversionMethod.D0;
}
return ConversionMethod.Invalid; if ((HasTag(profile, IccProfileTag.DToB1) || HasTag(profile, IccProfileTag.BToD1))
&& renderingIntent == IccRenderingIntent.MediaRelativeColorimetric)
{
return ConversionMethod.D1;
} }
private ConversionMethod CheckMethodA(IccProfile profile, IccRenderingIntent renderingIntent) if ((HasTag(profile, IccProfileTag.DToB2) || HasTag(profile, IccProfileTag.BToD2))
&& renderingIntent == IccRenderingIntent.Saturation)
{ {
if ((this.HasTag(profile, IccProfileTag.AToB0) || this.HasTag(profile, IccProfileTag.BToA0)) return ConversionMethod.D2;
&& renderingIntent == IccRenderingIntent.Perceptual) }
{
return ConversionMethod.A0;
}
if ((this.HasTag(profile, IccProfileTag.AToB1) || this.HasTag(profile, IccProfileTag.BToA1)) if ((HasTag(profile, IccProfileTag.DToB3) || HasTag(profile, IccProfileTag.BToD3))
&& renderingIntent == IccRenderingIntent.MediaRelativeColorimetric) && renderingIntent == IccRenderingIntent.AbsoluteColorimetric)
{ {
return ConversionMethod.A1; return ConversionMethod.D3;
} }
if ((this.HasTag(profile, IccProfileTag.AToB2) || this.HasTag(profile, IccProfileTag.BToA2)) return ConversionMethod.Invalid;
&& renderingIntent == IccRenderingIntent.Saturation) }
{
return ConversionMethod.A2;
}
return ConversionMethod.Invalid; private static ConversionMethod CheckMethodA(IccProfile profile, IccRenderingIntent renderingIntent)
{
if ((HasTag(profile, IccProfileTag.AToB0) || HasTag(profile, IccProfileTag.BToA0))
&& renderingIntent == IccRenderingIntent.Perceptual)
{
return ConversionMethod.A0;
} }
private ConversionMethod CheckMethodA0(IccProfile profile) if ((HasTag(profile, IccProfileTag.AToB1) || HasTag(profile, IccProfileTag.BToA1))
&& renderingIntent == IccRenderingIntent.MediaRelativeColorimetric)
{ {
bool valid = this.HasTag(profile, IccProfileTag.AToB0) || this.HasTag(profile, IccProfileTag.BToA0); return ConversionMethod.A1;
return valid ? ConversionMethod.A0 : ConversionMethod.Invalid;
} }
private ConversionMethod CheckMethodTrc(IccProfile profile) if ((HasTag(profile, IccProfileTag.AToB2) || HasTag(profile, IccProfileTag.BToA2))
&& renderingIntent == IccRenderingIntent.Saturation)
{ {
if (this.HasTag(profile, IccProfileTag.RedMatrixColumn) return ConversionMethod.A2;
&& this.HasTag(profile, IccProfileTag.GreenMatrixColumn)
&& this.HasTag(profile, IccProfileTag.BlueMatrixColumn)
&& this.HasTag(profile, IccProfileTag.RedTrc)
&& this.HasTag(profile, IccProfileTag.GreenTrc)
&& this.HasTag(profile, IccProfileTag.BlueTrc))
{
return ConversionMethod.ColorTrc;
}
if (this.HasTag(profile, IccProfileTag.GrayTrc))
{
return ConversionMethod.GrayTrc;
}
return ConversionMethod.Invalid;
} }
private ConversionMethod CheckMethod2(IccProfile profile) return ConversionMethod.Invalid;
{ }
if (this.HasTag(profile, IccProfileTag.DToB0) || this.HasTag(profile, IccProfileTag.BToD0))
{
return ConversionMethod.D0;
}
if (this.HasTag(profile, IccProfileTag.AToB0) || this.HasTag(profile, IccProfileTag.AToB0)) private static ConversionMethod CheckMethodA0(IccProfile profile)
{ {
return ConversionMethod.A0; bool valid = HasTag(profile, IccProfileTag.AToB0) || HasTag(profile, IccProfileTag.BToA0);
} return valid ? ConversionMethod.A0 : ConversionMethod.Invalid;
}
return ConversionMethod.Invalid; private static ConversionMethod CheckMethodTrc(IccProfile profile)
{
if (HasTag(profile, IccProfileTag.RedMatrixColumn)
&& HasTag(profile, IccProfileTag.GreenMatrixColumn)
&& HasTag(profile, IccProfileTag.BlueMatrixColumn)
&& HasTag(profile, IccProfileTag.RedTrc)
&& HasTag(profile, IccProfileTag.GreenTrc)
&& HasTag(profile, IccProfileTag.BlueTrc))
{
return ConversionMethod.ColorTrc;
} }
private bool HasTag(IccProfile profile, IccProfileTag tag) if (HasTag(profile, IccProfileTag.GrayTrc))
{ {
return profile.Entries.Any(t => t.TagSignature == tag); return ConversionMethod.GrayTrc;
} }
private IccTagDataEntry GetTag(IccProfile profile, IccProfileTag tag) return ConversionMethod.Invalid;
}
private static ConversionMethod CheckMethod2(IccProfile profile)
{
if (HasTag(profile, IccProfileTag.DToB0) || HasTag(profile, IccProfileTag.BToD0))
{ {
return profile.Entries.FirstOrDefault(t => t.TagSignature == tag); return ConversionMethod.D0;
} }
private T GetTag<T>(IccProfile profile, IccProfileTag tag) if (HasTag(profile, IccProfileTag.AToB0) || HasTag(profile, IccProfileTag.AToB0))
where T : IccTagDataEntry
{ {
return profile.Entries.OfType<T>().FirstOrDefault(t => t.TagSignature == tag); return ConversionMethod.A0;
} }
return ConversionMethod.Invalid;
} }
private static bool HasTag(IccProfile profile, IccProfileTag tag)
=> profile.Entries.Any(t => t.TagSignature == tag);
private static IccTagDataEntry GetTag(IccProfile profile, IccProfileTag tag)
=> profile.Entries.FirstOrDefault(t => t.TagSignature == tag);
private static T GetTag<T>(IccProfile profile, IccProfileTag tag)
where T : IccTagDataEntry
=> profile.Entries.OfType<T>().FirstOrDefault(t => t.TagSignature == tag);
} }

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterBase.ConversionMethod.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
{ {

62
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.Conversions.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System; using System;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
@ -22,57 +22,57 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
/// <param name="renderingIntent">The wanted rendering intent. Can be ignored if not available</param> /// <param name="renderingIntent">The wanted rendering intent. Can be ignored if not available</param>
protected void Init(IccProfile profile, bool toPcs, IccRenderingIntent renderingIntent) protected void Init(IccProfile profile, bool toPcs, IccRenderingIntent renderingIntent)
{ {
ConversionMethod method = this.GetConversionMethod(profile, renderingIntent); ConversionMethod method = GetConversionMethod(profile, renderingIntent);
switch (method) switch (method)
{ {
case ConversionMethod.D0: case ConversionMethod.D0:
this.calculator = toPcs ? this.calculator = toPcs ?
this.InitD(profile, IccProfileTag.DToB0) : InitD(profile, IccProfileTag.DToB0) :
this.InitD(profile, IccProfileTag.BToD0); InitD(profile, IccProfileTag.BToD0);
break; break;
case ConversionMethod.D1: case ConversionMethod.D1:
this.calculator = toPcs ? this.calculator = toPcs ?
this.InitD(profile, IccProfileTag.DToB1) : InitD(profile, IccProfileTag.DToB1) :
this.InitD(profile, IccProfileTag.BToD1); InitD(profile, IccProfileTag.BToD1);
break; break;
case ConversionMethod.D2: case ConversionMethod.D2:
this.calculator = toPcs ? this.calculator = toPcs ?
this.InitD(profile, IccProfileTag.DToB2) : InitD(profile, IccProfileTag.DToB2) :
this.InitD(profile, IccProfileTag.BToD2); InitD(profile, IccProfileTag.BToD2);
break; break;
case ConversionMethod.D3: case ConversionMethod.D3:
this.calculator = toPcs ? this.calculator = toPcs ?
this.InitD(profile, IccProfileTag.DToB3) : InitD(profile, IccProfileTag.DToB3) :
this.InitD(profile, IccProfileTag.BToD3); InitD(profile, IccProfileTag.BToD3);
break; break;
case ConversionMethod.A0: case ConversionMethod.A0:
this.calculator = toPcs ? this.calculator = toPcs ?
this.InitA(profile, IccProfileTag.AToB0) : InitA(profile, IccProfileTag.AToB0) :
this.InitA(profile, IccProfileTag.BToA0); InitA(profile, IccProfileTag.BToA0);
break; break;
case ConversionMethod.A1: case ConversionMethod.A1:
this.calculator = toPcs ? this.calculator = toPcs ?
this.InitA(profile, IccProfileTag.AToB1) : InitA(profile, IccProfileTag.AToB1) :
this.InitA(profile, IccProfileTag.BToA1); InitA(profile, IccProfileTag.BToA1);
break; break;
case ConversionMethod.A2: case ConversionMethod.A2:
this.calculator = toPcs ? this.calculator = toPcs ?
this.InitA(profile, IccProfileTag.AToB2) : InitA(profile, IccProfileTag.AToB2) :
this.InitA(profile, IccProfileTag.BToA2); InitA(profile, IccProfileTag.BToA2);
break; break;
case ConversionMethod.ColorTrc: case ConversionMethod.ColorTrc:
this.calculator = this.InitColorTrc(profile, toPcs); this.calculator = InitColorTrc(profile, toPcs);
break; break;
case ConversionMethod.GrayTrc: case ConversionMethod.GrayTrc:
this.calculator = this.InitGrayTrc(profile, toPcs); this.calculator = InitGrayTrc(profile, toPcs);
break; break;
case ConversionMethod.Invalid: case ConversionMethod.Invalid:
@ -81,9 +81,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
} }
} }
private IVector4Calculator InitA(IccProfile profile, IccProfileTag tag) private static IVector4Calculator InitA(IccProfile profile, IccProfileTag tag)
{ {
IccTagDataEntry entry = this.GetTag(profile, tag); IccTagDataEntry entry = GetTag(profile, tag);
switch (entry) switch (entry)
{ {
case IccLut8TagDataEntry lut8: case IccLut8TagDataEntry lut8:
@ -100,9 +100,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
} }
} }
private IVector4Calculator InitD(IccProfile profile, IccProfileTag tag) private static IVector4Calculator InitD(IccProfile profile, IccProfileTag tag)
{ {
IccMultiProcessElementsTagDataEntry entry = this.GetTag<IccMultiProcessElementsTagDataEntry>(profile, tag); IccMultiProcessElementsTagDataEntry entry = GetTag<IccMultiProcessElementsTagDataEntry>(profile, tag);
if (entry == null) if (entry == null)
{ {
throw new InvalidIccProfileException("Entry is null."); throw new InvalidIccProfileException("Entry is null.");
@ -111,15 +111,15 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
throw new NotImplementedException("Multi process elements are not supported"); throw new NotImplementedException("Multi process elements are not supported");
} }
private IVector4Calculator InitColorTrc(IccProfile profile, bool toPcs) private static IVector4Calculator InitColorTrc(IccProfile profile, bool toPcs)
{ {
IccXyzTagDataEntry redMatrixColumn = this.GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.RedMatrixColumn); IccXyzTagDataEntry redMatrixColumn = GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.RedMatrixColumn);
IccXyzTagDataEntry greenMatrixColumn = this.GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.GreenMatrixColumn); IccXyzTagDataEntry greenMatrixColumn = GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.GreenMatrixColumn);
IccXyzTagDataEntry blueMatrixColumn = this.GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.BlueMatrixColumn); IccXyzTagDataEntry blueMatrixColumn = GetTag<IccXyzTagDataEntry>(profile, IccProfileTag.BlueMatrixColumn);
IccTagDataEntry redTrc = this.GetTag(profile, IccProfileTag.RedTrc); IccTagDataEntry redTrc = GetTag(profile, IccProfileTag.RedTrc);
IccTagDataEntry greenTrc = this.GetTag(profile, IccProfileTag.GreenTrc); IccTagDataEntry greenTrc = GetTag(profile, IccProfileTag.GreenTrc);
IccTagDataEntry blueTrc = this.GetTag(profile, IccProfileTag.BlueTrc); IccTagDataEntry blueTrc = GetTag(profile, IccProfileTag.BlueTrc);
if (redMatrixColumn == null || if (redMatrixColumn == null ||
greenMatrixColumn == null || greenMatrixColumn == null ||
@ -141,9 +141,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Icc
toPcs); toPcs);
} }
private IVector4Calculator InitGrayTrc(IccProfile profile, bool toPcs) private static IVector4Calculator InitGrayTrc(IccProfile profile, bool toPcs)
{ {
IccTagDataEntry entry = this.GetTag(profile, IccProfileTag.GrayTrc); IccTagDataEntry entry = GetTag(profile, IccProfileTag.GrayTrc);
return new GrayTrcCalculator(entry, toPcs); return new GrayTrcCalculator(entry, toPcs);
} }
} }

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccConverterbase.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToDataConverter.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccDataToPcsConverter.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToDataConverter.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Icc/IccPcsToPcsConverter.cs

@ -1,5 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;

30
tests/ImageSharp.Tests/Colorspaces/Icc/Calculators/ClutCalculatorTests.cs

@ -1,29 +1,27 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Six Labors Split License.
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc; using SixLabors.ImageSharp.ColorSpaces.Conversion.Icc;
using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.Metadata.Profiles.Icc;
using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion; using SixLabors.ImageSharp.Tests.TestDataIcc.Conversion;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Colorspaces.Icc.Calculators namespace SixLabors.ImageSharp.Tests.Colorspaces.Icc.Calculators;
/// <summary>
/// Tests ICC <see cref="ClutCalculator"/>
/// </summary>
[Trait("Color", "Conversion")]
public class ClutCalculatorTests
{ {
/// <summary> [Theory]
/// Tests ICC <see cref="ClutCalculator"/> [MemberData(nameof(IccConversionDataClut.ClutConversionTestData), MemberType = typeof(IccConversionDataClut))]
/// </summary> internal void ClutCalculator_WithClut_ReturnsResult(IccClut lut, Vector4 input, Vector4 expected)
[Trait("Color", "Conversion")]
public class ClutCalculatorTests
{ {
[Theory] ClutCalculator calculator = new(lut);
[MemberData(nameof(IccConversionDataClut.ClutConversionTestData), MemberType = typeof(IccConversionDataClut))]
internal void ClutCalculator_WithClut_ReturnsResult(IccClut lut, Vector4 input, Vector4 expected)
{
var calculator = new ClutCalculator(lut);
Vector4 result = calculator.Calculate(input); Vector4 result = calculator.Calculate(input);
VectorAssert.Equal(expected, result, 4); VectorAssert.Equal(expected, result, 4);
}
} }
} }

Loading…
Cancel
Save