diff --git a/src/ImageProcessor/Colors/ColorTransforms.cs b/src/ImageProcessor/Colors/ColorTransforms.cs index fc3a01a78..7643db0b1 100644 --- a/src/ImageProcessor/Colors/ColorTransforms.cs +++ b/src/ImageProcessor/Colors/ColorTransforms.cs @@ -188,20 +188,20 @@ namespace ImageProcessor float x = cieLabColor.A / 500F + y; float z = y - cieLabColor.B / 200F; - float x3 = (float)Math.Pow(x, 3); - float y3 = (float)Math.Pow(y, 3); - float z3 = (float)Math.Pow(z, 3); + float x3 = x * x * x; + float y3 = y * y * y; + float z3 = z * z * z; y = (y3 > 0.008856F) ? y3 : (y - 16F / 116F) / 7.787F; x = (x3 > 0.008856F) ? x3 : (x - 16F / 116F) / 7.787F; z = (z3 > 0.008856F) ? z3 : (z - 16F / 116F) / 7.787F; // Then XYZ to RGB - 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); + 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 Color.InverseCompand(new Color(r, g, b)); + return Color.Compand(new Color(r, g, b)); } /// diff --git a/src/ImageProcessor/Colors/Colorspaces/CieLab.cs b/src/ImageProcessor/Colors/Colorspaces/CieLab.cs index 978e0f0ae..567937edb 100644 --- a/src/ImageProcessor/Colors/Colorspaces/CieLab.cs +++ b/src/ImageProcessor/Colors/Colorspaces/CieLab.cs @@ -82,9 +82,9 @@ namespace ImageProcessor // First convert to CIE XYZ color = Color.InverseCompand(color.Limited); - float x = (color.R * 0.41239079926595F) + (color.G * 0.35758433938387F) + (color.B * 0.18048078840183F); - float y = (color.R * 0.21263900587151F) + (color.G * 0.71516867876775F) + (color.B * 0.072192315360733F); - float z = (color.R * 0.019330818715591F) + (color.G * 0.11919477979462F) + (color.B * 0.95053215224966F); + 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; @@ -99,9 +99,9 @@ namespace ImageProcessor y = y > 0.008856 ? (float) Math.Pow(y, 1F / 3F) : (7.787F * y) + (16F / 116F); z = z > 0.008856 ? (float) Math.Pow(z, 1F / 3F) : (7.787F * z) + (16F / 116F); - float l = (116 * y) - 16; - float a = 500 * (x - y); - float b = 200 * (y - z); + float l = (116F * y) - 16F; + float a = 500F * (x - y); + float b = 200F * (y - z); return new CieLab(l, a, b); } diff --git a/tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs b/tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs index 6551b17c7..e68a7e74e 100644 --- a/tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs +++ b/tests/ImageProcessor.Tests/Colors/ColorConversionTests.cs @@ -334,5 +334,86 @@ namespace ImageProcessor.Tests Assert.Equal(color4, (Color)cmyk4); } } + + /// + /// Tests the implicit conversion from to . + /// Comparison values obtained from + /// http://colormine.org/convert/rgb-to-lab + /// http://au.mathworks.com/help/images/ref/rgb2lab.html + /// http://www.colorhexa.com/00ffff + /// L seems to match quite well, A and B tend to drift from the converter results a bit more + /// + [Fact] + public void ColorToCieLab() + { + // White + Color color = new Color(1, 1, 1); + CieLab cielab = color; + + Assert.Equal(100, cielab.L, 1); + Assert.Equal(0, cielab.A, 1); + Assert.Equal(0, cielab.B, 1); + + // Black + Color color2 = new Color(0, 0, 0); + CieLab cielab2 = color2; + Assert.Equal(0, cielab2.L, 1); + Assert.Equal(0, cielab2.A, 1); + Assert.Equal(0, cielab2.B, 1); + + //// Grey + Color color3 = new Color(128 / 255f, 128 / 255f, 128 / 255f); + CieLab cielab3 = color3; + Assert.Equal(53.6, cielab3.L, 1); + Assert.Equal(0, cielab3.A, 1); + Assert.Equal(0, cielab3.B, 1); + + //// Cyan + Color color4 = new Color(0, 1, 1); + CieLab cielab4 = color4; + Assert.Equal(91.1, cielab4.L, 1); + Assert.Equal(-48.1, cielab4.A, 1); + Assert.Equal(-14.1, cielab4.B, 1); + } + + /// + /// Tests the implicit conversion from to . + /// + [Fact] + public void CieLabToColor() + { + // Dark moderate pink. + CieLab cielab = new CieLab(36.5492f, 33.3173f, -12.0615f); + Color color = cielab; + + Assert.Equal(color.R, 128 / 255f, 1); + Assert.Equal(color.G, 64 / 255f, 2); + Assert.Equal(color.B, 106 / 255f, 1); + + // Ochre + CieLab cielab2 = new CieLab(58.1758f, 27.3399f, 56.8240f); + Color color2 = cielab2; + + Assert.Equal(color2.R, 204 / 255f, 1); + Assert.Equal(color2.G, 119 / 255f, 2); + Assert.Equal(color2.B, 34 / 255f, 1); + + //// White + CieLab cielab3 = new CieLab(0, 0, 0); + Color color3 = cielab3; + + Assert.Equal(color3.R, 0f, 1); + Assert.Equal(color3.G, 0f, 1); + Assert.Equal(color3.B, 0f, 1); + + //// 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)); + CieLab cielab4 = color4; + Assert.Equal(color4, (Color)cielab4); + } + } } }