/// <summary> /// Gets the distance between <paramref name="left"/> and <paramref name="right"/> based on the <see href="http://en.wikipedia.org/wiki/Color_difference#CIEDE2000">CIEDE2000</see> formula. /// </summary> /// <param name="left">An <see cref="CieLab"/> to compare.</param> /// <param name="right">An <see cref="CieLab"/> to compare.</param> /// <returns>Score based on similarity, the lower the score the closer that <paramref name="left"/> and <paramref name="right"/> are.</returns> public double Distance(CieLab left, CieLab right) { //Set weighting factors to 1 const double Kl = 1.0d; const double Kc = 1.0d; const double Kh = 1.0d; var deltaL = right.L - left.L; var c1ab = Ciede2000Comparison.Cab(left); var c2ab = Ciede2000Comparison.Cab(right); var g = 0.5d * (1 - Ciede2000Comparison.SqrtPow7((c1ab + c2ab) / 2)); var a1 = Ciede2000Comparison.A(left, g); var a2 = Ciede2000Comparison.A(right, g); var c1 = Ciede2000Comparison.C(left, a1); var c2 = Ciede2000Comparison.C(right, a2); var deltaC = c2 - c1; //Angles in Degree. var h1 = Ciede2000Comparison.H(left, a1); var h2 = Ciede2000Comparison.H(right, a2); //var h_bar = Math.Abs(h1 - h2); var deltaH = 2 * Math.Sqrt(c1 * c2) * Math.Sin(Ciede2000Comparison.DeltaHPrime(c1, c2, h1, h2) * Math.PI / 360d); // Calculate CIEDE2000 var cPrimeAverage = (c1 + c2) / 2d; var hPrimeAverage = Ciede2000Comparison.HPrimeAverage(c1, c2, h1, h2); var sL = Ciede2000Comparison.SL((left.L + right.L) / 2d); var sC = 1 + .045d * cPrimeAverage; var T = 1 - .17 * Math.Cos(this.DegToRad(hPrimeAverage - 30)) + .24 * Math.Cos(this.DegToRad(hPrimeAverage * 2)) + .32 * Math.Cos(this.DegToRad(hPrimeAverage * 3 + 6)) - .2 * Math.Cos(this.DegToRad(hPrimeAverage * 4 - 63)); var sH = 1 + .015 * T * cPrimeAverage; var rC = 2 * Ciede2000Comparison.SqrtPow7(cPrimeAverage); var rT = -Math.Sin(this.DegToRad(2 * (30 * Math.Exp(-Math.Pow((hPrimeAverage - 275) / 25, 2))))) * rC; var deltaCResult = deltaC / (sC * Kc); var deltaHResult = deltaH / (sH * Kh); return(Math.Sqrt(Math.Pow(deltaL / (sL * Kl), 2) + Math.Pow(deltaCResult, 2) + Math.Pow(deltaHResult, 2) + rT * deltaCResult * deltaHResult)); }
public void Convert_CieLab_to_YCbCr(float l, float a, float b, float y, float cb, float cr) { // Arrange var input = new CieLab(l, a, b); var expected = new YCbCr(y, cb, cr); Span <CieLab> inputSpan = new CieLab[5]; inputSpan.Fill(input); Span <YCbCr> actualSpan = new YCbCr[5]; // Act var actual = Converter.ToYCbCr(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_CieLab_to_Lms(float l, float a, float b, float l2, float m, float s) { // Arrange var input = new CieLab(l, a, b); var expected = new Lms(l2, m, s); Span <CieLab> inputSpan = new CieLab[5]; inputSpan.Fill(input); Span <Lms> actualSpan = new Lms[5]; // Act var actual = Converter.ToLms(input); Converter.Convert(inputSpan, actualSpan, actualSpan.Length); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_CieLab_to_LinearRgb(float l, float a, float b, float r, float g, float b2) { // Arrange var input = new CieLab(l, a, b); var expected = new LinearRgb(r, g, b2); Span <CieLab> inputSpan = new CieLab[5]; inputSpan.Fill(input); Span <LinearRgb> actualSpan = new LinearRgb[5]; // Act var actual = Converter.ToLinearRgb(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void CieLabToColor() { // Dark moderate pink. CieLab cielab = new CieLab(36.5492f, 33.3173f, -12.0615f); Rgba32 color = cielab; Assert.Equal(color.R, 128); Assert.Equal(color.G, 64); Assert.Equal(color.B, 106); // Ochre CieLab cielab2 = new CieLab(58.1758f, 27.3399f, 56.8240f); Rgba32 color2 = cielab2; Assert.Equal(color2.R, 204); Assert.Equal(color2.G, 119); Assert.Equal(color2.B, 34); // Black CieLab cielab3 = new CieLab(0, 0, 0); Rgba32 color3 = cielab3; Assert.Equal(color3.R, 0); Assert.Equal(color3.G, 0); Assert.Equal(color3.B, 0); // Check others. //Random random = new Random(0); //for (int i = 0; i < 1000; i++) //{ // Color color4 = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()); // CieLab cielab4 = color4; // Assert.Equal(color4, (Color)cielab4); //} }
public void Convert_CieLab_to_Cmyk(float l, float a, float b, float c, float m, float y, float k) { // Arrange var input = new CieLab(l, a, b); var expected = new Cmyk(c, m, y, k); Span <CieLab> inputSpan = new CieLab[5]; inputSpan.Fill(input); Span <Cmyk> actualSpan = new Cmyk[5]; // Act var actual = Converter.ToCmyk(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_Lch_to_Lab(float l, float c, float h, float l2, float a, float b) { // Arrange var input = new CieLch(l, c, h); var expected = new CieLab(l2, a, b); Span <CieLch> inputSpan = new CieLch[5]; inputSpan.Fill(input); Span <CieLab> actualSpan = new CieLab[5]; // Act var actual = Converter.ToCieLab(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_CieLab_to_CieLuv(float l, float a, float b, float l2, float u, float v) { // Arrange var input = new CieLab(l, a, b); var expected = new CieLuv(l2, u, v); Span <CieLab> inputSpan = new CieLab[5]; inputSpan.Fill(input); Span <CieLuv> actualSpan = new CieLuv[5]; // Act var actual = Converter.ToCieLuv(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_Hsv_to_CieLab(float h, float s, float v, float l, float a, float b) { // Arrange var input = new Hsv(h, s, v); var expected = new CieLab(l, a, b); Span <Hsv> inputSpan = new Hsv[5]; inputSpan.Fill(input); Span <CieLab> actualSpan = new CieLab[5]; // Act var actual = Converter.ToCieLab(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
public void Convert_CieXyy_to_CieLab(float x, float y, float yl, float l, float a, float b) { // Arrange var input = new CieXyy(x, y, yl); var expected = new CieLab(l, a, b); Span <CieXyy> inputSpan = new CieXyy[5]; inputSpan.Fill(input); Span <CieLab> actualSpan = new CieLab[5]; // Act var actual = Converter.ToCieLab(input); Converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
private static void ComputeColors() { pixels = new List <ConsolePixel>(); // char[] chars = { '█', '▓', '▒', '░' }; int[] rs = { 0, 0, 0, 0, 128, 128, 128, 192, 128, 0, 0, 0, 255, 255, 255, 255 }; int[] gs = { 0, 0, 128, 128, 0, 0, 128, 192, 128, 0, 255, 255, 0, 0, 255, 255 }; int[] bs = { 0, 128, 0, 128, 0, 128, 0, 192, 128, 255, 0, 255, 0, 255, 0, 255 }; for (int i = 0; i < 16; i++) { for (int j = i + 1; j < 16; j++) { var l1 = RGBtoLab(rs[i], gs[i], bs[i]); var l2 = RGBtoLab(rs[j], gs[j], bs[j]); for (int k = 0; k < 4; k++) { var l = CieLab.Combine(l1, l2, (4 - k) / 4.0); pixels.Add(new ConsolePixel { Char = '█', Forecolor = (ConsoleColor)i, Backcolor = (ConsoleColor)j, Lab = l }); } } } }
public void ColorToCieLab() { // White Rgba32 color = Rgba32.White; CieLab cielab = color; Assert.Equal(100, cielab.L, 3); Assert.Equal(0.005, cielab.A, 3); Assert.Equal(-0.010, cielab.B, 3); // Black Rgba32 color2 = Rgba32.Black; CieLab cielab2 = color2; Assert.Equal(0, cielab2.L, 3); Assert.Equal(0, cielab2.A, 3); Assert.Equal(0, cielab2.B, 3); // Gray Rgba32 color3 = Rgba32.Gray; CieLab cielab3 = color3; Assert.Equal(53.585, cielab3.L, 3); Assert.Equal(0.003, cielab3.A, 3); Assert.Equal(-0.006, cielab3.B, 3); // Cyan Rgba32 color4 = Rgba32.Cyan; CieLab cielab4 = color4; Assert.Equal(91.117, cielab4.L, 3); Assert.Equal(-48.080, cielab4.A, 3); Assert.Equal(-14.138, cielab4.B, 3); }
public void Convert_Xyz_to_Lab(float x, float y, float z, float l, float a, float b) { // Arrange var input = new CieXyz(x, y, z); var options = new ColorSpaceConverterOptions { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 }; var converter = new ColorSpaceConverter(options); var expected = new CieLab(l, a, b); Span <CieXyz> inputSpan = new CieXyz[5]; inputSpan.Fill(input); Span <CieLab> actualSpan = new CieLab[5]; // Act var actual = converter.ToCieLab(input); converter.Convert(inputSpan, actualSpan); // Assert Assert.Equal(expected, actual, ColorSpaceComparer); for (int i = 0; i < actualSpan.Length; i++) { Assert.Equal(expected, actualSpan[i], ColorSpaceComparer); } }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="LinearRgb"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="LinearRgb"/></returns> public LinearRgb ToLinearRgb(CieLab color) { Guard.NotNull(color, nameof(color)); var xyzColor = this.ToCieXyz(color); return(this.ToLinearRgb(xyzColor)); }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="CieLch"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="CieLch"/></returns> public CieLch ToCieLch(CieLab color) { // Adaptation CieLab adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color; // Conversion return(CieLabToCieLchConverter.Convert(adapted)); }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="YCbCr"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="YCbCr"/></returns> public YCbCr ToYCbCr(CieLab color) { Guard.NotNull(color, nameof(color)); var xyzColor = this.ToCieXyz(color); return(this.ToYCbCr(xyzColor)); }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="Hsl"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Hsl"/></returns> public Hsl ToHsl(CieLab color) { Guard.NotNull(color, nameof(color)); var xyzColor = this.ToCieXyz(color); return(this.ToHsl(xyzColor)); }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="Cmyk"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Cmyk"/></returns> public Cmyk ToCmyk(CieLab color) { Guard.NotNull(color, nameof(color)); var xyzColor = this.ToCieXyz(color); return(this.ToCmyk(xyzColor)); }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="CieLchuv"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="CieLchuv"/></returns> public CieLchuv ToCieLchuv(CieLab color) { Guard.NotNull(color, nameof(color)); CieXyz xyzColor = this.ToCieXyz(color); return(this.ToCieLchuv(xyzColor)); }
/// <summary> /// Converts a <see cref="CieXyz"/> into a <see cref="CieLchuv"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="CieLchuv"/></returns> public CieLchuv ToCieLchuv(CieXyz color) { Guard.NotNull(color, nameof(color)); CieLab labColor = this.ToCieLab(color); return(this.ToCieLchuv(labColor)); }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="HunterLab"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="HunterLab"/></returns> public HunterLab ToHunterLab(CieLab color) { Guard.NotNull(color, nameof(color)); var xyzColor = this.ToCieXyz(color); return(this.ToHunterLab(xyzColor)); }
/// <summary> /// Converts a <see cref="CieLch"/> into a <see cref="CieXyz"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="CieXyz"/></returns> public CieXyz ToCieXyz(CieLch color) { // Conversion to Lab CieLab labColor = CieLchToCieLabConverter.Convert(color); // Conversion to XYZ (incl. adaptation) return(this.ToCieXyz(labColor)); }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="Lms"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="Lms"/></returns> public Lms ToLms(CieLab color) { Guard.NotNull(color, nameof(color)); var xyzColor = this.ToCieXyz(color); return(this.ToLms(xyzColor)); }
private static bool ProcessImage(Bitmap image) { var bitmap = new Bitmap(image); CieLab prevCieLab = null; for (int i = 0; i < (int)(bitmap.Width * 0.05); i++) { for (int j = 0; j < (int)(bitmap.Height * 0.40); j++) { var pixel = bitmap.GetPixel(i, j); var xyz = pixel.ToXyz(); var cieLab = xyz.ToCieLab(); if (prevCieLab == null) { prevCieLab = cieLab; } else { var diff = GetDeltaE(prevCieLab, cieLab); if (diff > 5) { return(false); } prevCieLab = cieLab; } } } for (int i = bitmap.Width - (int)(bitmap.Width * 0.05); i < bitmap.Width; i++) { for (int j = 0; j < (int)(bitmap.Height * 0.40); j++) { var pixel = bitmap.GetPixel(i, j); var xyz = pixel.ToXyz(); var cieLab = xyz.ToCieLab(); if (prevCieLab == null) { prevCieLab = cieLab; } else { var diff = GetDeltaE(prevCieLab, cieLab); if (diff > 5) { return(false); } prevCieLab = cieLab; } } } return(true); }
public static CieLab Combine(CieLab l1, CieLab l2, double amount) { var l = l1.L * amount + l2.L * (1 - amount); var a = l1.A * amount + l2.A * (1 - amount); var b = l1.B * amount + l2.B * (1 - amount); return(new CieLab { L = l, A = a, B = b }); }
public void CieLabConstructorAssignsFields() { const float l = 75F; const float a = -64F; const float b = 87F; var cieLab = new CieLab(l, a, b); Assert.Equal(l, cieLab.L); Assert.Equal(a, cieLab.A); Assert.Equal(b, cieLab.B); }
/// <summary> /// Converts a <see cref="CieLab"/> into a <see cref="CieXyz"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="CieXyz"/></returns> public CieXyz ToCieXyz(CieLab color) { // Conversion CieXyz unadapted = CieLabToCieXyzConverter.Convert(color); // Adaptation CieXyz adapted = color.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed ? unadapted : this.Adapt(unadapted, color.WhitePoint); return(adapted); }
public void Convert_Lch_to_Lab(float l, float c, float h, float l2, float a, float b) { // Arrange CieLch input = new CieLch(l, c, h); // Act CieLab output = Converter.ToCieLab(input); // Assert Assert.Equal(l2, output.L, FloatRoundingComparer); Assert.Equal(a, output.A, FloatRoundingComparer); Assert.Equal(b, output.B, FloatRoundingComparer); }
public void Convert_Lab_to_LCHab(float l, float a, float b, float l2, float c, float h) { // Arrange CieLab input = new CieLab(l, a, b); // Act CieLch output = Converter.ToCieLch(input); // Assert Assert.Equal(l2, output.L, FloatRoundingComparer); Assert.Equal(c, output.C, FloatRoundingComparer); Assert.Equal(h, output.H, FloatRoundingComparer); }
/// <summary> /// Converts a <see cref="CieLch"/> into a <see cref="CieLab"/> /// </summary> /// <param name="color">The color to convert.</param> /// <returns>The <see cref="CieLab"/></returns> public CieLab ToCieLab(CieLch color) { // Conversion (perserving white point) CieLab unadapted = CieLchToCieLabConverter.Convert(color); if (!this.IsChromaticAdaptationPerformed) { return(unadapted); } // Adaptation return(this.Adapt(unadapted)); }