Browse Source

Remove duplicate Adaption checks and reduce allocations.

af/merge-core
James Jackson-South 8 years ago
parent
commit
09be4d225c
  1. 65
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
  2. 9
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
  3. 2
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
  4. 2
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
  5. 12
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
  6. 22
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
  7. 7
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs
  8. 24
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
  9. 21
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs

65
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation; using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion namespace SixLabors.ImageSharp.ColorSpaces.Conversion
@ -16,12 +15,26 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// Target white point is <see cref="ColorSpaceConverterOptions.WhitePoint"/>. /// Target white point is <see cref="ColorSpaceConverterOptions.WhitePoint"/>.
/// </summary> /// </summary>
/// <param name="color">The color to adapt</param> /// <param name="color">The color to adapt</param>
/// <param name="sourceWhitePoint">The white point to adapt for</param> /// <param name="sourceWhitePoint">The source white point.</param>
/// <returns>The adapted color</returns> /// <returns>The adapted color</returns>
public CieXyz Adapt(in CieXyz color, in CieXyz sourceWhitePoint) public CieXyz Adapt(in CieXyz color, in CieXyz sourceWhitePoint) => this.Adapt(color, sourceWhitePoint, this.whitePoint);
/// <summary>
/// Performs chromatic adaptation of given <see cref="CieXyz"/> color.
/// Target white point is <see cref="ColorSpaceConverterOptions.WhitePoint"/>.
/// </summary>
/// <param name="color">The color to adapt</param>
/// <param name="sourceWhitePoint">The source white point.</param>
/// <param name="targetWhitePoint">The target white point.</param>
/// <returns>The adapted color</returns>
public CieXyz Adapt(in CieXyz color, in CieXyz sourceWhitePoint, in CieXyz targetWhitePoint)
{ {
this.CheckChromaticAdaptation(); if (!this.performChromaticAdaptation || sourceWhitePoint.Equals(targetWhitePoint))
return this.chromaticAdaptation.Transform(color, sourceWhitePoint, this.whitePoint); {
return color;
}
return this.chromaticAdaptation.Transform(color, sourceWhitePoint, targetWhitePoint);
} }
/// <summary> /// <summary>
@ -31,9 +44,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The adapted color</returns> /// <returns>The adapted color</returns>
public CieLab Adapt(in CieLab color) public CieLab Adapt(in CieLab color)
{ {
this.CheckChromaticAdaptation(); if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetLabWhitePoint))
if (color.WhitePoint.Equals(this.targetLabWhitePoint))
{ {
return color; return color;
} }
@ -49,9 +60,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The adapted color</returns> /// <returns>The adapted color</returns>
public CieLch Adapt(in CieLch color) public CieLch Adapt(in CieLch color)
{ {
this.CheckChromaticAdaptation(); if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetLabWhitePoint))
if (color.WhitePoint.Equals(this.targetLabWhitePoint))
{ {
return color; return color;
} }
@ -67,9 +76,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The adapted color</returns> /// <returns>The adapted color</returns>
public CieLchuv Adapt(in CieLchuv color) public CieLchuv Adapt(in CieLchuv color)
{ {
this.CheckChromaticAdaptation(); if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetLabWhitePoint))
if (color.WhitePoint.Equals(this.targetLabWhitePoint))
{ {
return color; return color;
} }
@ -85,9 +92,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The adapted color</returns> /// <returns>The adapted color</returns>
public CieLuv Adapt(in CieLuv color) public CieLuv Adapt(in CieLuv color)
{ {
this.CheckChromaticAdaptation(); if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetLuvWhitePoint))
if (color.WhitePoint.Equals(this.targetLuvWhitePoint))
{ {
return color; return color;
} }
@ -103,9 +108,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The adapted color</returns> /// <returns>The adapted color</returns>
public HunterLab Adapt(in HunterLab color) public HunterLab Adapt(in HunterLab color)
{ {
this.CheckChromaticAdaptation(); if (!this.performChromaticAdaptation || color.WhitePoint.Equals(this.targetHunterLabWhitePoint))
if (color.WhitePoint.Equals(this.targetHunterLabWhitePoint))
{ {
return color; return color;
} }
@ -121,9 +124,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The adapted color</returns> /// <returns>The adapted color</returns>
public LinearRgb Adapt(in LinearRgb color) public LinearRgb Adapt(in LinearRgb color)
{ {
this.CheckChromaticAdaptation(); if (!this.performChromaticAdaptation || color.WorkingSpace.Equals(this.targetRgbWorkingSpace))
if (color.WorkingSpace.Equals(this.targetRgbWorkingSpace))
{ {
return color; return color;
} }
@ -136,8 +137,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
CieXyz adapted = this.chromaticAdaptation.Transform(unadapted, color.WorkingSpace.WhitePoint, this.targetRgbWorkingSpace.WhitePoint); CieXyz adapted = this.chromaticAdaptation.Transform(unadapted, color.WorkingSpace.WhitePoint, this.targetRgbWorkingSpace.WhitePoint);
// Conversion back to RGB // Conversion back to RGB
CieXyzToLinearRgbConverter converterToRGB = this.GetCieXyxToLinearRgbConverter(this.targetRgbWorkingSpace); return this.cieXyzToLinearRgbConverter.Convert(adapted);
return converterToRGB.Convert(adapted);
} }
/// <summary> /// <summary>
@ -147,19 +147,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The adapted color</returns> /// <returns>The adapted color</returns>
public Rgb Adapt(in Rgb color) public Rgb Adapt(in Rgb color)
{ {
var linearInput = this.ToLinearRgb(color);
LinearRgb linearOutput = this.Adapt(linearInput);
return this.ToRgb(linearOutput);
}
private void CheckChromaticAdaptation()
{
const string NoAdapterMessage = "Cannot perform chromatic adaptation, provide a chromatic adaptation method and white point.";
if (!this.performChromaticAdaptation) if (!this.performChromaticAdaptation)
{ {
throw new InvalidOperationException(NoAdapterMessage); return color;
} }
var linearInput = this.ToLinearRgb(color);
LinearRgb linearOutput = this.Adapt(linearInput);
return this.ToRgb(linearOutput);
} }
} }
} }

9
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs

@ -28,11 +28,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
// Conversion (perserving white point) // Conversion (perserving white point)
CieLab unadapted = CieLchToCieLabConverter.Convert(color); CieLab unadapted = CieLchToCieLabConverter.Convert(color);
if (!this.performChromaticAdaptation)
{
return unadapted;
}
// Adaptation // Adaptation
return this.Adapt(unadapted); return this.Adapt(unadapted);
} }
@ -165,9 +160,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public CieLab ToCieLab(in CieXyz color) public CieLab ToCieLab(in CieXyz color)
{ {
// Adaptation // Adaptation
CieXyz adapted = this.performLabChromaticAdaptation CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetLabWhitePoint);
? this.chromaticAdaptation.Transform(color, this.whitePoint, this.targetLabWhitePoint)
: color;
// Conversion // Conversion
return this.cieXyzToCieLabConverter.Convert(adapted); return this.cieXyzToCieLabConverter.Convert(adapted);

2
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public CieLch ToCieLch(in CieLab color) public CieLch ToCieLch(in CieLab color)
{ {
// Adaptation // Adaptation
CieLab adapted = this.performChromaticAdaptation ? this.Adapt(color) : color; CieLab adapted = this.Adapt(color);
// Conversion // Conversion
return CieLabToCieLchConverter.Convert(adapted); return CieLabToCieLchConverter.Convert(adapted);

2
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs

@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public CieLchuv ToCieLchuv(in CieLuv color) public CieLchuv ToCieLchuv(in CieLuv color)
{ {
// Adaptation // Adaptation
CieLuv adapted = this.performChromaticAdaptation ? this.Adapt(color) : color; CieLuv adapted = this.Adapt(color);
// Conversion // Conversion
return CieLuvToCieLchuvConverter.Convert(adapted); return CieLuvToCieLchuvConverter.Convert(adapted);

12
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs

@ -89,11 +89,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
// Conversion (perserving white point) // Conversion (perserving white point)
CieLuv unadapted = CieLchuvToCieLuvConverter.Convert(color); CieLuv unadapted = CieLchuvToCieLuvConverter.Convert(color);
if (!this.performChromaticAdaptation)
{
return unadapted;
}
// Adaptation // Adaptation
return this.Adapt(unadapted); return this.Adapt(unadapted);
} }
@ -159,13 +154,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public CieLuv ToCieLuv(in CieXyz color) public CieLuv ToCieLuv(in CieXyz color)
{ {
// Adaptation // Adaptation
CieXyz adapted = !this.whitePoint.Equals(this.targetLabWhitePoint) && this.performChromaticAdaptation CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetLabWhitePoint);
? this.chromaticAdaptation.Transform(color, this.whitePoint, this.targetLabWhitePoint)
: color;
// Conversion // Conversion
var converter = new CieXyzToCieLuvConverter(this.targetLuvWhitePoint); return this.cieXyzToCieLuvConverter.Convert(adapted);
return converter.Convert(adapted);
} }
/// <summary> /// <summary>

22
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs

@ -32,11 +32,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
CieXyz unadapted = CieLabToCieXyzConverter.Convert(color); CieXyz unadapted = CieLabToCieXyzConverter.Convert(color);
// Adaptation // Adaptation
CieXyz adapted = color.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation return this.Adapt(unadapted, color.WhitePoint);
? unadapted
: this.Adapt(unadapted, color.WhitePoint);
return adapted;
} }
/// <summary> /// <summary>
@ -141,11 +137,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
CieXyz unadapted = CieLuvToCieXyzConverter.Convert(color); CieXyz unadapted = CieLuvToCieXyzConverter.Convert(color);
// Adaptation // Adaptation
CieXyz adapted = color.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation return this.Adapt(unadapted, color.WhitePoint);
? unadapted
: this.Adapt(unadapted, color.WhitePoint);
return adapted;
} }
/// <summary> /// <summary>
@ -314,11 +306,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color); CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color);
// Adaptation // Adaptation
CieXyz adapted = color.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation return this.Adapt(unadapted, color.WhitePoint);
? unadapted
: this.Adapt(unadapted, color.WhitePoint);
return adapted;
} }
/// <summary> /// <summary>
@ -354,9 +342,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
CieXyz unadapted = converter.Convert(color); CieXyz unadapted = converter.Convert(color);
// Adaptation // Adaptation
return color.WorkingSpace.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation return this.Adapt(unadapted, color.WorkingSpace.WhitePoint);
? unadapted
: this.Adapt(unadapted, color.WorkingSpace.WhitePoint);
} }
/// <summary> /// <summary>

7
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs

@ -4,7 +4,6 @@
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{ {
@ -181,12 +180,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public HunterLab ToHunterLab(in CieXyz color) public HunterLab ToHunterLab(in CieXyz color)
{ {
// Adaptation // Adaptation
CieXyz adapted = !this.whitePoint.Equals(this.targetHunterLabWhitePoint) && this.performChromaticAdaptation CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetHunterLabWhitePoint);
? this.chromaticAdaptation.Transform(color, this.whitePoint, this.targetHunterLabWhitePoint)
: color;
// Conversion // Conversion
return new CieXyzToHunterLabConverter(this.targetHunterLabWhitePoint).Convert(adapted); return this.cieXyzToHunterLabConverter.Convert(adapted);
} }
/// <summary> /// <summary>

24
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs

@ -15,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{ {
private static readonly RgbToLinearRgbConverter RgbToLinearRgbConverter = new RgbToLinearRgbConverter(); private static readonly RgbToLinearRgbConverter RgbToLinearRgbConverter = new RgbToLinearRgbConverter();
private CieXyzToLinearRgbConverter cieXyzToLinearRgbConverter;
/// <summary> /// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="LinearRgb"/> /// Converts a <see cref="CieLab"/> into a <see cref="LinearRgb"/>
/// </summary> /// </summary>
@ -185,13 +183,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public LinearRgb ToLinearRgb(in CieXyz color) public LinearRgb ToLinearRgb(in CieXyz color)
{ {
// Adaptation // Adaptation
CieXyz adapted = this.targetRgbWorkingSpace.WhitePoint.Equals(this.whitePoint) || !this.performChromaticAdaptation CieXyz adapted = this.Adapt(color, this.whitePoint, this.targetRgbWorkingSpace.WhitePoint);
? color
: this.chromaticAdaptation.Transform(color, this.whitePoint, this.targetRgbWorkingSpace.WhitePoint);
// Conversion // Conversion
CieXyzToLinearRgbConverter xyzConverter = this.GetCieXyxToLinearRgbConverter(this.targetRgbWorkingSpace); return this.cieXyzToLinearRgbConverter.Convert(adapted);
return xyzConverter.Convert(adapted);
} }
/// <summary> /// <summary>
@ -438,20 +433,5 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
dp = this.ToLinearRgb(sp); dp = this.ToLinearRgb(sp);
} }
} }
/// <summary>
/// Gets the correct converter for the given rgb working space.
/// </summary>
/// <param name="workingSpace">The target working space</param>
/// <returns>The <see cref="CieXyzToLinearRgbConverter"/></returns>
private CieXyzToLinearRgbConverter GetCieXyxToLinearRgbConverter(RgbWorkingSpace workingSpace)
{
if (this.cieXyzToLinearRgbConverter != null && this.cieXyzToLinearRgbConverter.TargetWorkingSpace.Equals(workingSpace))
{
return this.cieXyzToLinearRgbConverter;
}
return this.cieXyzToLinearRgbConverter = new CieXyzToLinearRgbConverter(workingSpace);
}
} }
} }

21
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs

@ -12,18 +12,19 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public partial class ColorSpaceConverter public partial class ColorSpaceConverter
{ {
// Options. // Options.
private Matrix4x4 lmsAdaptationMatrix;
private CieXyz whitePoint; private CieXyz whitePoint;
private CieXyz targetLuvWhitePoint; private CieXyz targetLuvWhitePoint;
private CieXyz targetLabWhitePoint; private CieXyz targetLabWhitePoint;
private CieXyz targetHunterLabWhitePoint; private CieXyz targetHunterLabWhitePoint;
private RgbWorkingSpace targetRgbWorkingSpace; private readonly RgbWorkingSpace targetRgbWorkingSpace;
private IChromaticAdaptation chromaticAdaptation; private readonly IChromaticAdaptation chromaticAdaptation;
private bool performChromaticAdaptation; private readonly bool performChromaticAdaptation;
private bool performLabChromaticAdaptation; private readonly CieXyzAndLmsConverter cieXyzAndLmsConverter;
private Matrix4x4 lmsAdaptationMatrix; private readonly CieXyzToCieLabConverter cieXyzToCieLabConverter;
private readonly CieXyzToCieLuvConverter cieXyzToCieLuvConverter;
private CieXyzAndLmsConverter cieXyzAndLmsConverter; private readonly CieXyzToHunterLabConverter cieXyzToHunterLabConverter;
private CieXyzToCieLabConverter cieXyzToCieLabConverter; private readonly CieXyzToLinearRgbConverter cieXyzToLinearRgbConverter;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ColorSpaceConverter"/> class. /// Initializes a new instance of the <see cref="ColorSpaceConverter"/> class.
@ -47,11 +48,13 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
this.targetRgbWorkingSpace = options.TargetRgbWorkingSpace; this.targetRgbWorkingSpace = options.TargetRgbWorkingSpace;
this.chromaticAdaptation = options.ChromaticAdaptation; this.chromaticAdaptation = options.ChromaticAdaptation;
this.performChromaticAdaptation = this.chromaticAdaptation != null; this.performChromaticAdaptation = this.chromaticAdaptation != null;
this.performLabChromaticAdaptation = !this.whitePoint.Equals(this.targetLabWhitePoint) && this.performChromaticAdaptation;
this.lmsAdaptationMatrix = options.LmsAdaptationMatrix; this.lmsAdaptationMatrix = options.LmsAdaptationMatrix;
this.cieXyzAndLmsConverter = new CieXyzAndLmsConverter(this.lmsAdaptationMatrix); this.cieXyzAndLmsConverter = new CieXyzAndLmsConverter(this.lmsAdaptationMatrix);
this.cieXyzToCieLabConverter = new CieXyzToCieLabConverter(this.targetLabWhitePoint); this.cieXyzToCieLabConverter = new CieXyzToCieLabConverter(this.targetLabWhitePoint);
this.cieXyzToCieLuvConverter = new CieXyzToCieLuvConverter(this.targetLuvWhitePoint);
this.cieXyzToHunterLabConverter = new CieXyzToHunterLabConverter(this.targetHunterLabWhitePoint);
this.cieXyzToLinearRgbConverter = new CieXyzToLinearRgbConverter(this.targetRgbWorkingSpace);
} }
} }
} }
Loading…
Cancel
Save