diff --git a/src/ImageProcessor/Colors/ColorTransforms.cs b/src/ImageProcessor/Colors/ColorTransforms.cs
index 5b7ca2a41..e5ef27697 100644
--- a/src/ImageProcessor/Colors/ColorTransforms.cs
+++ b/src/ImageProcessor/Colors/ColorTransforms.cs
@@ -67,29 +67,27 @@ namespace ImageProcessor
return new Color(r, g, b);
}
+ ///
+ /// Allows the implicit conversion of an instance of to a
+ /// .
+ ///
+ /// The instance of to convert.
+ ///
+ /// An instance of .
+ ///
public static implicit operator Color(CieXyz color)
{
- var x = color.X;
- var y = color.Y;
- var z = color.Z;
-
- // assume sRGB
- // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
- float r = (x * 3.240969941904521F) + (y * -1.537383177570093F) + (z * -0.498610760293F);
- float g = (x * -0.96924363628087F) + (y * 1.87596750150772F) + (z * 0.041555057407175F);
- float b = (x * 0.055630079696993F) + (y * -0.20397695888897F) + (z * 1.056971514242878F);
-
- r = r > 0.0031308 ? (float)((1.055 * Math.Pow(r, 1.0 / 2.4)) - 0.055) : r = (r * 12.92F);
+ float x = color.X / 100F;
+ float y = color.Y / 100F;
+ float z = color.Z / 100F;
- g = g > 0.0031308 ? (float)((1.055 * Math.Pow(g, 1.0 / 2.4)) - 0.055) : g = (g * 12.92F);
-
- b = b > 0.0031308 ? (float)((1.055 * Math.Pow(b, 1.0 / 2.4)) - 0.055) : b = (b * 12.92F);
+ // Then XYZ to RGB (multiplication by 100 was done above already)
- r = Math.Min(Math.Max(0, r), 1);
- g = Math.Min(Math.Max(0, g), 1);
- b = Math.Min(Math.Max(0, b), 1);
+ float r = (x * 3.2406F) + (y * -1.5372F) + (z * -0.4986F);
+ float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F);
+ float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F);
- return new Color(r, g, b);
+ return Color.Compress(new Color(r, g, b));
}
///
diff --git a/src/ImageProcessor/Colors/Colorspaces/CieXyz.cs b/src/ImageProcessor/Colors/Colorspaces/CieXyz.cs
index db8f57b38..9f577da81 100644
--- a/src/ImageProcessor/Colors/Colorspaces/CieXyz.cs
+++ b/src/ImageProcessor/Colors/Colorspaces/CieXyz.cs
@@ -34,10 +34,10 @@ namespace ImageProcessor
public CieXyz(float x, float y, float z)
: this()
{
- // ToDo: check clamp values
- this.backingVector.X = x.Clamp(0, 2);
- this.backingVector.Y = y.Clamp(0, 2);
- this.backingVector.Z = z.Clamp(0, 2);
+ // Not clamping as documentation about this space seems to indicate "usual" ranges
+ this.backingVector.X = x;
+ this.backingVector.Y = y;
+ this.backingVector.Z = z;
}
///
@@ -76,18 +76,15 @@ namespace ImageProcessor
///
public static implicit operator CieXyz(Color color)
{
- var r = color.R;
- var g = color.G;
- var b = color.B;
-
- // assume sRGB
- r = r > 0.04045 ? (float)Math.Pow(((r + 0.055) / 1.055), 2.4) : (float)(r / 12.92);
- g = g > 0.04045 ? (float)Math.Pow(((g + 0.055) / 1.055), 2.4) : (float)(g / 12.92);
- b = b > 0.04045 ? (float)Math.Pow(((b + 0.055) / 1.055), 2.4) : (float)(b / 12.92);
-
- var x = (r * 0.41239079926595F) + (g * 0.35758433938387F) + (b * 0.18048078840183F);
- var y = (r * 0.21263900587151F) + (g * 0.71516867876775F) + (b * 0.072192315360733F);
- var z = (r * 0.019330818715591F) + (g * 0.11919477979462F) + (b * 0.95053215224966F);
+ color = Color.Expand(color.Limited);
+
+ float x = (color.R * 0.4124F) + (color.G * 0.3576F) + (color.B * 0.1805F);
+ float y = (color.R * 0.2126F) + (color.G * 0.7152F) + (color.B * 0.0722F);
+ float z = (color.R * 0.0193F) + (color.G * 0.1192F) + (color.B * 0.9505F);
+
+ x *= 100F;
+ y *= 100F;
+ z *= 100F;
return new CieXyz(x, y, z);
}
diff --git a/tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs b/tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs
index f63d4d0f8..0a1563cc6 100644
--- a/tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs
+++ b/tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs
@@ -91,32 +91,84 @@ namespace ImageProcessor.Tests
Assert.Equal(1f, color3.A, 1);
}
+ ///
+ /// Tests the implicit conversion from to .
+ /// Comparison values obtained from
+ /// http://colormine.org/convert/rgb-to-xyz
+ ///
[Fact]
public void ColorToCieXyz()
{
+ // White
Color color = new Color(1, 1, 1);
- CieXyz cieXyz = color;
+ CieXyz ciexyz = color;
+
+ Assert.Equal(95.05f, ciexyz.X, 3);
+ Assert.Equal(100.0f, ciexyz.Y, 3);
+ Assert.Equal(108.900f, ciexyz.Z, 3);
+
+ // Black
+ Color color2 = new Color(0, 0, 0);
+ CieXyz ciexyz2 = color2;
+ Assert.Equal(0, ciexyz2.X, 3);
+ Assert.Equal(0, ciexyz2.Y, 3);
+ Assert.Equal(0, ciexyz2.Z, 3);
+
+ //// Grey
+ Color color3 = new Color(128 / 255f, 128 / 255f, 128 / 255f);
+ CieXyz ciexyz3 = color3;
+ Assert.Equal(20.518, ciexyz3.X, 3);
+ Assert.Equal(21.586, ciexyz3.Y, 3);
+ Assert.Equal(23.507, ciexyz3.Z, 3);
- Assert.Equal(0.9505F, cieXyz.X, 4);
- Assert.Equal(1.0000F, cieXyz.Y, 4);
- Assert.Equal(1.089F, cieXyz.Z, 3);
-
+ //// Cyan
+ Color color4 = new Color(0, 1, 1);
+ CieXyz ciexyz4 = color4;
+ Assert.Equal(53.810f, ciexyz4.X, 3);
+ Assert.Equal(78.740f, ciexyz4.Y, 3);
+ Assert.Equal(106.970f, ciexyz4.Z, 3);
}
+ ///
+ /// Tests the implicit conversion from to .
+ /// Comparison values obtained from
+ /// http://colormine.org/convert/rgb-to-xyz
+ ///
[Fact]
public void CieXyzToColor()
{
- CieXyz cieXyz = new CieXyz(0.25F, 0.40F, 0.10F);
- Color color = cieXyz;
+ // Dark moderate pink.
+ CieXyz ciexyz = new CieXyz(13.337f, 9.297f, 14.727f);
+ Color color = ciexyz;
- Assert.Equal(0.4174F, color.R, 3);
- Assert.Equal(0.7434F, color.G, 3);
- Assert.Equal(0.2162F, color.B, 2);
+ Assert.Equal(128 / 255f, color.R, 3);
+ Assert.Equal(64 / 255f, color.G, 3);
+ Assert.Equal(106 / 255f, color.B, 3);
- //xyz2rgb([0.25 0.40 0.10])
- //ans = 0.4174 0.7434 0.2152
+ // Ochre
+ CieXyz ciexyz2 = new CieXyz(31.787f, 26.147f, 4.885f);
+ Color color2 = ciexyz2;
+
+ Assert.Equal(204 / 255f, color2.R, 3);
+ Assert.Equal(119 / 255f, color2.G, 3);
+ Assert.Equal(34 / 255f, color2.B, 3);
+
+ //// White
+ CieXyz ciexyz3 = new CieXyz(0, 0, 0);
+ Color color3 = ciexyz3;
+ Assert.Equal(0f, color3.R, 3);
+ Assert.Equal(0f, color3.G, 3);
+ Assert.Equal(0f, color3.B, 3);
+ //// Check others.
+ Random random = new Random(0);
+ for (int i = 0; i < 1000; i++)
+ {
+ Color color4 = new Color(random.Next(1), random.Next(1), random.Next(1));
+ CieXyz ciexyz4 = color4;
+ Assert.Equal(color4, (Color)ciexyz4);
+ }
}
///