diff --git a/src/ImageSharp/Colors/Spaces/Cmyk.cs b/src/ImageSharp/Colors/Spaces/Cmyk.cs
new file mode 100644
index 000000000..488c36e8e
--- /dev/null
+++ b/src/ImageSharp/Colors/Spaces/Cmyk.cs
@@ -0,0 +1,149 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Colors.Spaces
+{
+ using System;
+ using System.ComponentModel;
+ using System.Numerics;
+
+ ///
+ /// Represents an CMYK (cyan, magenta, yellow, keyline) color.
+ ///
+ public struct Cmyk : IEquatable, IAlmostEquatable
+ {
+ ///
+ /// Represents a that has C, M, Y, and K values set to zero.
+ ///
+ public static readonly Cmyk Empty = default(Cmyk);
+
+ ///
+ /// The backing vector for SIMD support.
+ ///
+ private readonly Vector4 backingVector;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The cyan component.
+ /// The magenta component.
+ /// The yellow component.
+ /// The keyline black component.
+ public Cmyk(float c, float m, float y, float k)
+ : this()
+ {
+ this.backingVector = Vector4.Clamp(new Vector4(c, m, y, k), Vector4.Zero, Vector4.One);
+ }
+
+ ///
+ /// Gets the cyan color component.
+ /// A value ranging between 0 and 1.
+ ///
+ public float C => this.backingVector.X;
+
+ ///
+ /// Gets the magenta color component.
+ /// A value ranging between 0 and 1.
+ ///
+ public float M => this.backingVector.Y;
+
+ ///
+ /// Gets the yellow color component.
+ /// A value ranging between 0 and 1.
+ ///
+ public float Y => this.backingVector.Z;
+
+ ///
+ /// Gets the keyline black color component.
+ /// A value ranging between 0 and 1.
+ ///
+ public float K => this.backingVector.W;
+
+ ///
+ /// Gets a value indicating whether this is empty.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool IsEmpty => this.Equals(Empty);
+
+ ///
+ /// Compares two objects for equality.
+ ///
+ ///
+ /// The on the left side of the operand.
+ ///
+ ///
+ /// The on the right side of the operand.
+ ///
+ ///
+ /// True if the current left is equal to the parameter; otherwise, false.
+ ///
+ public static bool operator ==(Cmyk left, Cmyk right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Compares two objects for inequality
+ ///
+ ///
+ /// The on the left side of the operand.
+ ///
+ ///
+ /// The on the right side of the operand.
+ ///
+ ///
+ /// True if the current left is unequal to the parameter; otherwise, false.
+ ///
+ public static bool operator !=(Cmyk left, Cmyk right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return this.backingVector.GetHashCode();
+ }
+
+ ///
+ public override string ToString()
+ {
+ if (this.IsEmpty)
+ {
+ return "Cmyk [Empty]";
+ }
+
+ return $"Cmyk [ C={this.C:#0.##}, M={this.M:#0.##}, Y={this.Y:#0.##}, K={this.K:#0.##}]";
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj is Cmyk)
+ {
+ return this.Equals((Cmyk)obj);
+ }
+
+ return false;
+ }
+
+ ///
+ public bool Equals(Cmyk other)
+ {
+ return this.backingVector.Equals(other.backingVector);
+ }
+
+ ///
+ public bool AlmostEquals(Cmyk other, float precision)
+ {
+ Vector4 result = Vector4.Abs(this.backingVector - other.backingVector);
+
+ return result.X <= precision
+ && result.Y <= precision
+ && result.Z <= precision
+ && result.W <= precision;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLab.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLab.cs
index dfc5fbe4a..95582d2b3 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLab.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLab.cs
@@ -20,30 +20,32 @@ namespace ImageSharp.Colors.Spaces.Conversion
private static readonly CieLchToCieLabConverter CieLchToCieLabConverter = new CieLchToCieLabConverter();
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLab ToCieLab(CieXyz color)
+ public CieLab ToCieLab(CieLch color)
{
Guard.NotNull(color, nameof(color));
- // Adaptation
- CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed
- ? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetLabWhitePoint)
- : color;
+ // Conversion (perserving white point)
+ CieLab unadapted = CieLchToCieLabConverter.Convert(color);
- // Conversion
- CieXyzToCieLabConverter converter = new CieXyzToCieLabConverter(this.TargetLabWhitePoint);
- return converter.Convert(adapted);
+ if (!this.IsChromaticAdaptationPerformed)
+ {
+ return unadapted;
+ }
+
+ // Adaptation
+ return this.Adapt(unadapted);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLab ToCieLab(LinearRgb color)
+ public CieLab ToCieLab(CieXyy color)
{
Guard.NotNull(color, nameof(color));
@@ -52,11 +54,30 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLab ToCieLab(Rgb color)
+ public CieLab ToCieLab(CieXyz color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ // Adaptation
+ CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed
+ ? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetLabWhitePoint)
+ : color;
+
+ // Conversion
+ CieXyzToCieLabConverter converter = new CieXyzToCieLabConverter(this.TargetLabWhitePoint);
+ return converter.Convert(adapted);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public CieLab ToCieLab(Cmyk color)
{
Guard.NotNull(color, nameof(color));
@@ -91,11 +112,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLab ToCieLab(CieXyy color)
+ public CieLab ToCieLab(LinearRgb color)
{
Guard.NotNull(color, nameof(color));
@@ -104,24 +125,16 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLab ToCieLab(CieLch color)
+ public CieLab ToCieLab(Rgb color)
{
Guard.NotNull(color, nameof(color));
- // Conversion (perserving white point)
- CieLab unadapted = CieLchToCieLabConverter.Convert(color);
-
- if (!this.IsChromaticAdaptationPerformed)
- {
- return unadapted;
- }
-
- // Adaptation
- return this.Adapt(unadapted);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToCieLab(xyzColor);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLch.cs
index 0ad1f53d2..79fa53c82 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLch.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieLch.cs
@@ -17,6 +17,35 @@ namespace ImageSharp.Colors.Spaces.Conversion
///
private static readonly CieLabToCieLchConverter CieLabToCieLchConverter = new CieLabToCieLchConverter();
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public CieLch ToCieLch(CieLab color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ // Adaptation
+ CieLab adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color;
+
+ // Conversion
+ return CieLabToCieLchConverter.Convert(adapted);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public CieLch ToCieLch(CieXyy color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToCieLch(xyzColor);
+ }
+
///
/// Converts a into a
///
@@ -31,45 +60,42 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLch ToCieLch(Rgb color)
+ public CieLch ToCieLch(Cmyk color)
{
Guard.NotNull(color, nameof(color));
- CieLab labColor = this.ToCieLab(color);
- return this.ToCieLch(labColor);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToCieLch(xyzColor);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLch ToCieLch(LinearRgb color)
+ public CieLch ToCieLch(HunterLab color)
{
Guard.NotNull(color, nameof(color));
- CieLab labColor = this.ToCieLab(color);
- return this.ToCieLch(labColor);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToCieLch(xyzColor);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLch ToCieLch(CieLab color)
+ public CieLch ToCieLch(LinearRgb color)
{
Guard.NotNull(color, nameof(color));
- // Adaptation
- CieLab adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color;
-
- // Conversion
- return CieLabToCieLchConverter.Convert(adapted);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToCieLch(xyzColor);
}
///
@@ -81,21 +107,21 @@ namespace ImageSharp.Colors.Spaces.Conversion
{
Guard.NotNull(color, nameof(color));
- CieLab labColor = this.ToCieLab(color);
- return this.ToCieLch(labColor);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToCieLch(xyzColor);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieLch ToCieLch(HunterLab color)
+ public CieLch ToCieLch(Rgb color)
{
Guard.NotNull(color, nameof(color));
- CieLab labColor = this.ToCieLab(color);
- return this.ToCieLch(labColor);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToCieLch(xyzColor);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyy.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyy.cs
index 692b13f94..0b86109af 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyy.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyy.cs
@@ -15,23 +15,25 @@ namespace ImageSharp.Colors.Spaces.Conversion
private static readonly CieXyzAndCieXyyConverter CieXyzAndCieXyyConverter = new CieXyzAndCieXyyConverter();
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(CieXyz color)
+ public CieXyy ToCieXyy(CieLab color)
{
Guard.NotNull(color, nameof(color));
- return CieXyzAndCieXyyConverter.Convert(color);
+ CieXyz xyzColor = this.ToCieXyz(color);
+
+ return this.ToCieXyy(xyzColor);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(CieLab color)
+ public CieXyy ToCieXyy(CieLch color)
{
Guard.NotNull(color, nameof(color));
@@ -41,11 +43,23 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(CieLch color)
+ public CieXyy ToCieXyy(CieXyz color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ return CieXyzAndCieXyyConverter.Convert(color);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public CieXyy ToCieXyy(Cmyk color)
{
Guard.NotNull(color, nameof(color));
@@ -83,11 +97,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(Rgb color)
+ public CieXyy ToCieXyy(Lms color)
{
Guard.NotNull(color, nameof(color));
@@ -97,11 +111,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyy ToCieXyy(Lms color)
+ public CieXyy ToCieXyy(Rgb color)
{
Guard.NotNull(color, nameof(color));
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyz.cs
index c04f1093b..7e171d42e 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyz.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.CieXyz.cs
@@ -41,6 +41,22 @@ namespace ImageSharp.Colors.Spaces.Conversion
return adapted;
}
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public CieXyz ToCieXyz(CieLch color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ // Conversion to Lab
+ CieLab labColor = CieLchToCieLabConverter.Convert(color);
+
+ // Conversion to XYZ (incl. adaptation)
+ return this.ToCieXyz(labColor);
+ }
+
///
/// Converts a into a
///
@@ -55,30 +71,38 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(Lms color)
+ public CieXyz ToCieXyz(Cmyk color)
{
Guard.NotNull(color, nameof(color));
// Conversion
- return this.cachedCieXyzAndLmsConverter.Convert(color);
+ Rgb rgb = this.ToRgb(color);
+
+ return this.ToCieXyz(rgb);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(Rgb color)
+ public CieXyz ToCieXyz(HunterLab color)
{
Guard.NotNull(color, nameof(color));
// Conversion
- LinearRgb linear = RgbToLinearRgbConverter.Convert(color);
- return this.ToCieXyz(linear);
+ CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color);
+
+ // Adaptation
+ CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed
+ ? unadapted
+ : this.Adapt(unadapted, color.WhitePoint);
+
+ return adapted;
}
///
@@ -96,44 +120,35 @@ namespace ImageSharp.Colors.Spaces.Conversion
// Adaptation
return color.WorkingSpace.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed
- ? unadapted
- : this.Adapt(unadapted, color.WorkingSpace.WhitePoint);
+ ? unadapted
+ : this.Adapt(unadapted, color.WorkingSpace.WhitePoint);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(HunterLab color)
+ public CieXyz ToCieXyz(Lms color)
{
Guard.NotNull(color, nameof(color));
// Conversion
- CieXyz unadapted = HunterLabToCieXyzConverter.Convert(color);
-
- // Adaptation
- CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed
- ? unadapted
- : this.Adapt(unadapted, color.WhitePoint);
-
- return adapted;
+ return this.cachedCieXyzAndLmsConverter.Convert(color);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public CieXyz ToCieXyz(CieLch color)
+ public CieXyz ToCieXyz(Rgb color)
{
Guard.NotNull(color, nameof(color));
- // Conversion to Lab
- CieLab labColor = CieLchToCieLabConverter.Convert(color);
-
- // Conversion to XYZ (incl. adaptation)
- return this.ToCieXyz(labColor);
+ // Conversion
+ LinearRgb linear = RgbToLinearRgbConverter.Convert(color);
+ return this.ToCieXyz(linear);
}
///
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Cmyk.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Cmyk.cs
new file mode 100644
index 000000000..dc7e10927
--- /dev/null
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Cmyk.cs
@@ -0,0 +1,128 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Colors.Spaces.Conversion
+{
+ using ImageSharp.Colors.Spaces;
+ using ImageSharp.Colors.Spaces.Conversion.Implementation.Cmyk;
+
+ ///
+ /// Converts between color spaces ensuring that the color is adapted using chromatic adaptation.
+ ///
+ public partial class ColorSpaceConverter
+ {
+ private static readonly CmykAndRgbConverter CmykAndRgbConverter = new CmykAndRgbConverter();
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Cmyk ToCmyk(CieLab color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ CieXyz xyzColor = this.ToCieXyz(color);
+
+ return this.ToCmyk(xyzColor);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Cmyk ToCmyk(CieLch color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ CieXyz xyzColor = this.ToCieXyz(color);
+
+ return this.ToCmyk(xyzColor);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Cmyk ToCmyk(CieXyy color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ CieXyz xyzColor = this.ToCieXyz(color);
+
+ return this.ToCmyk(xyzColor);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Cmyk ToCmyk(CieXyz color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ Rgb rgb = this.ToRgb(color);
+
+ return CmykAndRgbConverter.Convert(rgb);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Cmyk ToCmyk(HunterLab color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ CieXyz xyzColor = this.ToCieXyz(color);
+
+ return this.ToCmyk(xyzColor);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Cmyk ToCmyk(LinearRgb color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ Rgb rgb = this.ToRgb(color);
+
+ return CmykAndRgbConverter.Convert(rgb);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Cmyk ToCmyk(Lms color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ CieXyz xyzColor = this.ToCieXyz(color);
+
+ return this.ToCmyk(xyzColor);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Cmyk ToCmyk(Rgb color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ return CmykAndRgbConverter.Convert(color);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.HunterLab.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.HunterLab.cs
index 961b43fd2..6d8442387 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.HunterLab.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.HunterLab.cs
@@ -13,29 +13,24 @@ namespace ImageSharp.Colors.Spaces.Conversion
public partial class ColorSpaceConverter
{
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieXyz color)
+ public HunterLab ToHunterLab(CieLab color)
{
Guard.NotNull(color, nameof(color));
- // Adaptation
- CieXyz adapted = !this.WhitePoint.Equals(this.TargetHunterLabWhitePoint) && this.IsChromaticAdaptationPerformed
- ? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetHunterLabWhitePoint)
- : color;
-
- // Conversion
- return new CieXyzToHunterLabConverter(this.TargetHunterLabWhitePoint).Convert(adapted);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToHunterLab(xyzColor);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(Rgb color)
+ public HunterLab ToHunterLab(CieLch color)
{
Guard.NotNull(color, nameof(color));
@@ -44,11 +39,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(LinearRgb color)
+ public HunterLab ToHunterLab(CieXyy color)
{
Guard.NotNull(color, nameof(color));
@@ -57,11 +52,29 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieLab color)
+ public HunterLab ToHunterLab(CieXyz color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ // Adaptation
+ CieXyz adapted = !this.WhitePoint.Equals(this.TargetHunterLabWhitePoint) && this.IsChromaticAdaptationPerformed
+ ? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetHunterLabWhitePoint)
+ : color;
+
+ // Conversion
+ return new CieXyzToHunterLabConverter(this.TargetHunterLabWhitePoint).Convert(adapted);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public HunterLab ToHunterLab(Cmyk color)
{
Guard.NotNull(color, nameof(color));
@@ -70,11 +83,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(Lms color)
+ public HunterLab ToHunterLab(LinearRgb color)
{
Guard.NotNull(color, nameof(color));
@@ -83,11 +96,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieLch color)
+ public HunterLab ToHunterLab(Lms color)
{
Guard.NotNull(color, nameof(color));
@@ -96,11 +109,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public HunterLab ToHunterLab(CieXyy color)
+ public HunterLab ToHunterLab(Rgb color)
{
Guard.NotNull(color, nameof(color));
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.LinearRgb.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.LinearRgb.cs
index c7389918e..d381634d2 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.LinearRgb.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.LinearRgb.cs
@@ -17,16 +17,42 @@ namespace ImageSharp.Colors.Spaces.Conversion
private CieXyzToLinearRgbConverter cieXyzToLinearRgbConverter;
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(Rgb color)
+ public LinearRgb ToLinearRgb(CieLab color)
{
Guard.NotNull(color, nameof(color));
- // Conversion
- return RgbToLinearRgbConverter.Convert(color);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToLinearRgb(xyzColor);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public LinearRgb ToLinearRgb(CieLch color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToLinearRgb(xyzColor);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public LinearRgb ToLinearRgb(CieXyy color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToLinearRgb(xyzColor);
}
///
@@ -49,24 +75,24 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(HunterLab color)
+ public LinearRgb ToLinearRgb(Cmyk color)
{
Guard.NotNull(color, nameof(color));
- CieXyz xyzColor = this.ToCieXyz(color);
- return this.ToLinearRgb(xyzColor);
+ Rgb rgb = this.ToRgb(color);
+ return this.ToLinearRgb(rgb);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(CieLab color)
+ public LinearRgb ToLinearRgb(HunterLab color)
{
Guard.NotNull(color, nameof(color));
@@ -88,29 +114,16 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
- ///
- /// The color to convert.
- /// The
- public LinearRgb ToLinearRgb(CieLch color)
- {
- Guard.NotNull(color, nameof(color));
-
- CieXyz xyzColor = this.ToCieXyz(color);
- return this.ToLinearRgb(xyzColor);
- }
-
- ///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public LinearRgb ToLinearRgb(CieXyy color)
+ public LinearRgb ToLinearRgb(Rgb color)
{
Guard.NotNull(color, nameof(color));
- CieXyz xyzColor = this.ToCieXyz(color);
- return this.ToLinearRgb(xyzColor);
+ // Conversion
+ return RgbToLinearRgbConverter.Convert(color);
}
///
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Lms.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Lms.cs
index 74a6dd639..202ecf4dd 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Lms.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Lms.cs
@@ -13,24 +13,24 @@ namespace ImageSharp.Colors.Spaces.Conversion
public partial class ColorSpaceConverter
{
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Lms ToLms(CieXyz color)
+ public Lms ToLms(CieLab color)
{
Guard.NotNull(color, nameof(color));
- // Conversion
- return this.cachedCieXyzAndLmsConverter.Convert(color);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToLms(xyzColor);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Lms ToLms(CieLab color)
+ public Lms ToLms(CieLch color)
{
Guard.NotNull(color, nameof(color));
@@ -39,11 +39,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Lms ToLms(HunterLab color)
+ public Lms ToLms(CieXyy color)
{
Guard.NotNull(color, nameof(color));
@@ -52,11 +52,24 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Lms ToLms(LinearRgb color)
+ public Lms ToLms(CieXyz color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ // Conversion
+ return this.cachedCieXyzAndLmsConverter.Convert(color);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Lms ToLms(Cmyk color)
{
Guard.NotNull(color, nameof(color));
@@ -65,11 +78,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Lms ToLms(Rgb color)
+ public Lms ToLms(HunterLab color)
{
Guard.NotNull(color, nameof(color));
@@ -78,11 +91,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Lms ToLms(CieLch color)
+ public Lms ToLms(LinearRgb color)
{
Guard.NotNull(color, nameof(color));
@@ -91,11 +104,11 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Lms ToLms(CieXyy color)
+ public Lms ToLms(Rgb color)
{
Guard.NotNull(color, nameof(color));
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Rgb.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Rgb.cs
index 50b79bd2b..2682b05aa 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Rgb.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.Rgb.cs
@@ -15,40 +15,37 @@ namespace ImageSharp.Colors.Spaces.Conversion
private static readonly LinearRgbToRgbConverter LinearRgbToRgbConverter = new LinearRgbToRgbConverter();
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Rgb ToRgb(LinearRgb color)
+ public Rgb ToRgb(CieLab color)
{
Guard.NotNull(color, nameof(color));
- // Conversion
- return LinearRgbToRgbConverter.Convert(color);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToRgb(xyzColor);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieXyz color)
+ public Rgb ToRgb(CieLch color)
{
Guard.NotNull(color, nameof(color));
- // Conversion
- LinearRgb linear = this.ToLinearRgb(color);
-
- // Compand
- return this.ToRgb(linear);
+ CieXyz xyzColor = this.ToCieXyz(color);
+ return this.ToRgb(xyzColor);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Rgb ToRgb(HunterLab color)
+ public Rgb ToRgb(CieXyy color)
{
Guard.NotNull(color, nameof(color));
@@ -57,37 +54,40 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieLab color)
+ public Rgb ToRgb(CieXyz color)
{
Guard.NotNull(color, nameof(color));
- CieXyz xyzColor = this.ToCieXyz(color);
- return this.ToRgb(xyzColor);
+ // Conversion
+ LinearRgb linear = this.ToLinearRgb(color);
+
+ // Compand
+ return this.ToRgb(linear);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Rgb ToRgb(Lms color)
+ public Rgb ToRgb(Cmyk color)
{
Guard.NotNull(color, nameof(color));
- CieXyz xyzColor = this.ToCieXyz(color);
- return this.ToRgb(xyzColor);
+ // Conversion
+ return CmykAndRgbConverter.Convert(color);
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieLch color)
+ public Rgb ToRgb(HunterLab color)
{
Guard.NotNull(color, nameof(color));
@@ -96,11 +96,24 @@ namespace ImageSharp.Colors.Spaces.Conversion
}
///
- /// Converts a into a
+ /// Converts a into a
///
/// The color to convert.
/// The
- public Rgb ToRgb(CieXyy color)
+ public Rgb ToRgb(LinearRgb color)
+ {
+ Guard.NotNull(color, nameof(color));
+
+ // Conversion
+ return LinearRgbToRgbConverter.Convert(color);
+ }
+
+ ///
+ /// Converts a into a
+ ///
+ /// The color to convert.
+ /// The
+ public Rgb ToRgb(Lms color)
{
Guard.NotNull(color, nameof(color));
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.cs b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.cs
index 8727c4e6a..2de2947e4 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/ColorSpaceConverter.cs
@@ -21,6 +21,7 @@ namespace ImageSharp.Colors.Spaces.Conversion
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65;
private Matrix4x4 transformationMatrix;
+
private CieXyzAndLmsConverter cachedCieXyzAndLmsConverter;
///
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs b/src/ImageSharp/Colors/Spaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs
index dedb95ff8..9909697d6 100644
--- a/src/ImageSharp/Colors/Spaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs
+++ b/src/ImageSharp/Colors/Spaces/Conversion/Implementation/CieXyy/CieXyzAndCieXyyConverter.cs
@@ -1,4 +1,4 @@
-//
+//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
diff --git a/src/ImageSharp/Colors/Spaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs b/src/ImageSharp/Colors/Spaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs
new file mode 100644
index 000000000..98a7d8f3b
--- /dev/null
+++ b/src/ImageSharp/Colors/Spaces/Conversion/Implementation/Cmyk/CmykAndRgbConverter.cs
@@ -0,0 +1,50 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Colors.Spaces.Conversion.Implementation.Cmyk
+{
+ using System;
+
+ using ImageSharp.Colors.Spaces;
+
+ ///
+ /// Color converter between CMYK and Rgb
+ ///
+ internal class CmykAndRgbConverter : IColorConversion, IColorConversion
+ {
+ ///
+ public Rgb Convert(Cmyk input)
+ {
+ float r = (1F - input.C) * (1F - input.K);
+ float g = (1F - input.M) * (1F - input.K);
+ float b = (1F - input.Y) * (1F - input.K);
+
+ return new Rgb(r, g, b);
+ }
+
+ ///
+ public Cmyk Convert(Rgb input)
+ {
+ // To CMYK
+ float c = 1F - input.R;
+ float m = 1F - input.G;
+ float y = 1F - input.B;
+
+ // To CMYK
+ float k = MathF.Min(c, MathF.Min(m, y));
+
+ if (Math.Abs(k - 1F) < Constants.Epsilon)
+ {
+ return new Cmyk(0, 0, 0, 1F);
+ }
+
+ c = (c - k) / (1F - k);
+ m = (m - k) / (1F - k);
+ y = (y - k) / (1F - k);
+
+ return new Cmyk(c, m, y, k);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCieXyzConversionTest.cs b/tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCieXyzConversionTest.cs
index 4f18d2621..112ef5305 100644
--- a/tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCieXyzConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCieXyzConversionTest.cs
@@ -11,7 +11,7 @@
///
///
/// Test data generated using:
- /// http://www.brucelindbloom.com/index.html?ColorCalculator.html
+ ///
///
public class RgbAndCieXyzConversionTest
{
@@ -38,10 +38,10 @@
Rgb output = converter.ToRgb(input);
// Assert
- Assert.Equal(output.WorkingSpace, Rgb.DefaultWorkingSpace); // TODO: Change Assert.Equal to the correct order, first the expected, then the current value
- Assert.Equal(output.R, r, FloatRoundingComparer);
- Assert.Equal(output.G, g, FloatRoundingComparer);
- Assert.Equal(output.B, b, FloatRoundingComparer);
+ Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
+ Assert.Equal(r, output.R, FloatRoundingComparer);
+ Assert.Equal(g, output.G, FloatRoundingComparer);
+ Assert.Equal(b, output.B, FloatRoundingComparer);
}
///
@@ -66,10 +66,10 @@
Rgb output = converter.ToRgb(input);
// Assert
- Assert.Equal(output.WorkingSpace, Rgb.DefaultWorkingSpace);
- Assert.Equal(output.R, r, FloatRoundingComparer);
- Assert.Equal(output.G, g, FloatRoundingComparer);
- Assert.Equal(output.B, b, FloatRoundingComparer);
+ Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
+ Assert.Equal(r, output.R, FloatRoundingComparer);
+ Assert.Equal(g, output.G, FloatRoundingComparer);
+ Assert.Equal(b, output.B, FloatRoundingComparer);
}
///
@@ -93,9 +93,9 @@
CieXyz output = converter.ToCieXyz(input);
// Assert
- Assert.Equal(output.X, x, FloatRoundingComparer);
- Assert.Equal(output.Y, y, FloatRoundingComparer);
- Assert.Equal(output.Z, z, FloatRoundingComparer);
+ Assert.Equal(x, output.X, FloatRoundingComparer);
+ Assert.Equal(y, output.Y, FloatRoundingComparer);
+ Assert.Equal(z, output.Z, FloatRoundingComparer);
}
///
@@ -119,9 +119,9 @@
CieXyz output = converter.ToCieXyz(input);
// Assert
- Assert.Equal(output.X, x, FloatRoundingComparer);
- Assert.Equal(output.Y, y, FloatRoundingComparer);
- Assert.Equal(output.Z, z, FloatRoundingComparer);
+ Assert.Equal(x, output.X, FloatRoundingComparer);
+ Assert.Equal(y, output.Y, FloatRoundingComparer);
+ Assert.Equal(z, output.Z, FloatRoundingComparer);
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCmykConversionTest.cs b/tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCmykConversionTest.cs
new file mode 100644
index 000000000..50e187254
--- /dev/null
+++ b/tests/ImageSharp.Tests/Colors/Colorspaces/RgbAndCmykConversionTest.cs
@@ -0,0 +1,68 @@
+namespace ImageSharp.Tests.Colors.Colorspaces
+{
+ using System.Collections.Generic;
+
+ using ImageSharp.Colors.Spaces;
+ using ImageSharp.Colors.Spaces.Conversion;
+
+ using Xunit;
+
+ ///
+ /// Tests - conversions.
+ ///
+ ///
+ /// Test data generated using:
+ ///
+ ///
+ ///
+ public class RgbAndCmykConversionTest
+ {
+ private static readonly IEqualityComparer FloatRoundingComparer = new FloatRoundingComparer(4);
+
+ private static readonly ColorSpaceConverter Converter = new ColorSpaceConverter();
+
+ ///
+ /// Tests conversion from to .
+ ///
+ [Theory]
+ [InlineData(1, 1, 1, 1, 0, 0, 0)]
+ [InlineData(0, 0, 0, 0, 1, 1, 1)]
+ [InlineData(0, 0.84, 0.037, 0.365, 0.635, 0.1016, 0.6115)]
+ public void Convert_Cmyk_To_Rgb(float c, float m, float y, float k, float r, float g, float b)
+ {
+ // Arrange
+ Cmyk input = new Cmyk(c, m, y, k);
+
+ // Act
+ Rgb output = Converter.ToRgb(input);
+
+ // Assert
+ Assert.Equal(Rgb.DefaultWorkingSpace, output.WorkingSpace);
+ Assert.Equal(r, output.R, FloatRoundingComparer);
+ Assert.Equal(g, output.G, FloatRoundingComparer);
+ Assert.Equal(b, output.B, FloatRoundingComparer);
+ }
+
+ ///
+ /// Tests conversion from to .
+ ///
+ [Theory]
+ [InlineData(1, 1, 1, 0, 0, 0, 0)]
+ [InlineData(0, 0, 0, 0, 0, 0, 1)]
+ [InlineData(0.635, 0.1016, 0.6115, 0, 0.84, 0.037, 0.365)]
+ public void Convert_Rgb_To_Cmyk(float r, float g, float b, float c, float m, float y, float k)
+ {
+ // Arrange
+ Rgb input = new Rgb(r, g, b);
+
+ // Act
+ Cmyk output = Converter.ToCmyk(input);
+
+ // Assert
+ Assert.Equal(c, output.C, FloatRoundingComparer);
+ Assert.Equal(m, output.M, FloatRoundingComparer);
+ Assert.Equal(y, output.Y, FloatRoundingComparer);
+ Assert.Equal(k, output.K, FloatRoundingComparer);
+ }
+ }
+}