Example #1
0
        /// <summary>
        /// Converts CIEXYZ to CIELab structure.
        /// </summary>
        public static CIELab XYZtoLab(double x, double y, double z)
        {
            CIELab lab = CIELab.Empty;

            lab.L = 116.0 * Fxyz(y / CIEXYZ.D65.Y) - 16;
            lab.A = 500.0 * (Fxyz(x / CIEXYZ.D65.X) - Fxyz(y / CIEXYZ.D65.Y));
            lab.B = 200.0 * (Fxyz(y / CIEXYZ.D65.Y) - Fxyz(z / CIEXYZ.D65.Z));

            return(lab);
        }
Example #2
0
        // ******************************************************************
        // EO: Based on: http://www.easyrgb.com/index.php?X=DELT&H=04#text4
        // Based on: Delta E 1994
        public static double GetDistanceBetweenCie1994(CIELab lab1, CIELab lab2)
        {
            const double whtL = 1;
            const double whtC = 1;
            const double whtH = 1;                           //Weighting factors depending
            //on the application (1 = default)

            double xC1 = Math.Sqrt(Math.Pow(lab1.a, 2.0) + Math.Pow(lab1.b, 2.0));
            double xC2 = Math.Sqrt(Math.Pow(lab2.a, 2.0) + Math.Pow(lab2.b, 2.0));
            double xDL = lab2.l - lab1.l;
            double xDC = xC2 - xC1;
            double xDE = Math.Sqrt(
                ((lab1.l - lab2.l) * (lab1.l - lab2.l))
                + ((lab1.a - lab2.a) * (lab1.a - lab2.a))
                + ((lab1.b - lab2.b) * (lab1.b - lab2.b)));

            double xDH;

            if (Math.Sqrt(xDE) > (Math.Sqrt(Math.Abs(xDL)) + Math.Sqrt(Math.Abs(xDC))))
            {
                xDH = Math.Sqrt((xDE * xDE) - (xDL * xDL) - (xDC * xDC));
            }
            else
            {
                xDH = 0;
            }

            double xSC = 1 + (0.045 * xC1);
            double xSH = 1 + (0.015 * xC1);

            xDL /= whtL;
            xDC /= whtC * xSC;
            xDH /= whtH * xSH;
            double deltaE94 = Math.Sqrt(Math.Pow(xDL, 2.0) + Math.Pow(xDC, 2.0) + Math.Pow(xDH, 2.0));

            return(deltaE94);
        }
 /// <summary>
 /// Gets the "distance" between two colors calculated with CIELab algo
 /// </summary>
 /// EO Added 2011-09-08
 /// <param name="color1">First color.</param>
 /// <param name="color2">Second color.</param>
 public static double GetColorDistanceCIELab(Color c1, Color c2)
 {
     return(CIELab.GetDistanceBetweenCie2000(RGBtoLab(c1), RGBtoLab(c2)));
 }
 /// <summary>
 /// Converts CIELab to RGB.
 /// </summary>
 public static RGB LabtoRGB(CIELab lab)
 {
     return(XYZtoRGB(LabtoXYZ(lab)));
 }
 /// <summary>
 /// Converts CIELab to CIEXYZ.
 /// </summary>
 public static CIEXYZ LabtoXYZ(CIELab lab)
 {
     return(LabtoXYZ(lab.L, lab.A, lab.B));
 }
Example #6
0
 /// <summary>
 /// Converts CIELab to CIEXYZ.
 /// </summary>
 public static CIEXYZ LabtoXYZ(CIELab lab)
 {
     return LabtoXYZ(lab.L, lab.A, lab.B);
 }
Example #7
0
 /// <summary>
 /// Converts CIELab to RGB.
 /// </summary>
 public static RGB LabtoRGB(CIELab lab)
 {
     return XYZtoRGB(LabtoXYZ(lab));
 }
Example #8
0
        // ******************************************************************
        // Given by Rob2412 http://www.codeproject.com/KB/recipes/colorspace1.aspx?msg=4041550#xx4041550xx
        // and should be better then the previous one.
        /// <summary>
        /// Returns the color difference (distance) between a sample color CIELap(2) and a reference color CIELap(1)
        /// <para>in accorance with CIE 2000 alogorithm.</para>
        /// </summary>
        /// <param name="lab1">CIELap reference color.</param>
        /// <param name="lab2">CIELap sample color.</param>
        /// <returns>Color difference.</returns>
        public static double GetDistanceBetweenCie2000(CIELab lab1, CIELab lab2)
        {
            double p25 = Math.Pow(25, 7);

            double C1 = Math.Sqrt(lab1.A * lab1.A + lab1.B * lab1.B);
            double C2 = Math.Sqrt(lab2.A * lab2.A + lab2.B * lab2.B);
            double avgC = (C1 + C2) / 2F;

            double powAvgC = Math.Pow(avgC, 7);
            double G = (1 - Math.Sqrt(powAvgC / (powAvgC + p25))) / 2D;

            double a_1 = lab1.A * (1 + G);
            double a_2 = lab2.A * (1 + G);

            double C_1 = Math.Sqrt(a_1 * a_1 + lab1.B * lab1.B);
            double C_2 = Math.Sqrt(a_2 * a_2 + lab2.B * lab2.B);
            double avgC_ = (C_1 + C_2) / 2D;

            double h1 = (Atan(lab1.B, a_1) >= 0 ? Atan(lab1.B, a_1) : Atan(lab1.B, a_1) + 360F);
            double h2 = (Atan(lab2.B, a_2) >= 0 ? Atan(lab2.B, a_2) : Atan(lab2.B, a_2) + 360F);

            double H = (h1 - h2 > 180D ? (h1 + h2 + 360F) / 2D : (h1 + h2) / 2D);

            double T = 1;
            T -= 0.17 * Cos(H - 30);
            T += 0.24 * Cos(2 * H);
            T += 0.32 * Cos(3 * H + 6);
            T -= 0.20 * Cos(4 * H - 63);

            double deltah = 0;
            if (h2 - h1 <= 180)
                deltah = h2 - h1;
            else if (h2 <= h1)
                deltah = h2 - h1 + 360;
            else
                deltah = h2 - h1 - 360;

            double avgL = (lab1.L + lab2.L) / 2F;
            double deltaL_ = lab2.L - lab1.L;
            double deltaC_ = C_2 - C_1;
            double deltaH_ = 2 * Math.Sqrt(C_1 * C_2) * Sin(deltah / 2);

            double SL = 1 + (0.015 * Math.Pow(avgL - 50, 2)) / Math.Sqrt(20 + Math.Pow(avgL - 50, 2));
            double SC = 1 + 0.045 * avgC_;
            double SH = 1 + 0.015 * avgC_ * T;

            double exp = Math.Pow((H - 275) / 25, 2);
            double teta = Math.Pow(30, -exp);

            double RC = 2D * Math.Sqrt(Math.Pow(avgC_, 7) / (Math.Pow(avgC_, 7) + p25));
            double RT = -RC * Sin(2 * teta);

            double deltaE = 0;
            deltaE = Math.Pow(deltaL_ / SL, 2);
            deltaE += Math.Pow(deltaC_ / SC, 2);
            deltaE += Math.Pow(deltaH_ / SH, 2);
            deltaE += RT * (deltaC_ / SC) * (deltaH_ / SH);
            deltaE = Math.Sqrt(deltaE);

            return deltaE;
        }
Example #9
0
        // ******************************************************************
        // EO: Based on: http://www.easyrgb.com/index.php?X=DELT&H=04#text4
        // Based on: Delta E 1994
        public static double GetDistanceBetweenCie1994(CIELab lab1, CIELab lab2)
        {
            const double whtL = 1;
            const double whtC = 1;
            const double whtH = 1;               //Weighting factors depending
                                           //on the application (1 = default)

            double xC1 = Math.Sqrt(Math.Pow(lab1.a, 2.0) + Math.Pow(lab1.b, 2.0));
            double xC2 = Math.Sqrt(Math.Pow(lab2.a, 2.0) + Math.Pow(lab2.b, 2.0));
            double xDL = lab2.l - lab1.l;
            double xDC = xC2 - xC1;
            double xDE = Math.Sqrt(
                ((lab1.l - lab2.l) * (lab1.l - lab2.l))
                + ((lab1.a - lab2.a) * (lab1.a - lab2.a))
                + ((lab1.b - lab2.b) * (lab1.b - lab2.b)));

            double xDH;
            if (Math.Sqrt( xDE ) > ( Math.Sqrt( Math.Abs( xDL ) ) + Math.Sqrt( Math.Abs( xDC ) ) ) )
            {
                xDH = Math.Sqrt((xDE*xDE) - (xDL*xDL) - (xDC*xDC));
            }
            else
            {
                xDH = 0;
            }

            double xSC = 1 + (0.045*xC1);
            double xSH = 1 + (0.015*xC1);
            xDL /= whtL;
            xDC /= whtC*xSC;
            xDH /= whtH*xSH;
            double deltaE94 = Math.Sqrt(Math.Pow(xDL, 2.0) + Math.Pow(xDC, 2.0) + Math.Pow(xDH, 2.0));
            return deltaE94;
        }
Example #10
0
        // ******************************************************************
        // Given by Rob2412 http://www.codeproject.com/KB/recipes/colorspace1.aspx?msg=4041550#xx4041550xx
        // and should be better then the previous one.
        /// <summary>
        /// Returns the color difference (distance) between a sample color CIELap(2) and a reference color CIELap(1)
        /// <para>in accorance with CIE 2000 alogorithm.</para>
        /// </summary>
        /// <param name="lab1">CIELap reference color.</param>
        /// <param name="lab2">CIELap sample color.</param>
        /// <returns>Color difference.</returns>
        public static double GetDistanceBetweenCie2000(CIELab lab1, CIELab lab2)
        {
            double p25 = Math.Pow(25, 7);

            double C1   = Math.Sqrt(lab1.A * lab1.A + lab1.B * lab1.B);
            double C2   = Math.Sqrt(lab2.A * lab2.A + lab2.B * lab2.B);
            double avgC = (C1 + C2) / 2F;

            double powAvgC = Math.Pow(avgC, 7);
            double G       = (1 - Math.Sqrt(powAvgC / (powAvgC + p25))) / 2D;

            double a_1 = lab1.A * (1 + G);
            double a_2 = lab2.A * (1 + G);

            double C_1   = Math.Sqrt(a_1 * a_1 + lab1.B * lab1.B);
            double C_2   = Math.Sqrt(a_2 * a_2 + lab2.B * lab2.B);
            double avgC_ = (C_1 + C_2) / 2D;

            double h1 = (Atan(lab1.B, a_1) >= 0 ? Atan(lab1.B, a_1) : Atan(lab1.B, a_1) + 360F);
            double h2 = (Atan(lab2.B, a_2) >= 0 ? Atan(lab2.B, a_2) : Atan(lab2.B, a_2) + 360F);

            double H = (h1 - h2 > 180D ? (h1 + h2 + 360F) / 2D : (h1 + h2) / 2D);

            double T = 1;

            T -= 0.17 * Cos(H - 30);
            T += 0.24 * Cos(2 * H);
            T += 0.32 * Cos(3 * H + 6);
            T -= 0.20 * Cos(4 * H - 63);

            double deltah = 0;

            if (h2 - h1 <= 180)
            {
                deltah = h2 - h1;
            }
            else if (h2 <= h1)
            {
                deltah = h2 - h1 + 360;
            }
            else
            {
                deltah = h2 - h1 - 360;
            }

            double avgL    = (lab1.L + lab2.L) / 2F;
            double deltaL_ = lab2.L - lab1.L;
            double deltaC_ = C_2 - C_1;
            double deltaH_ = 2 * Math.Sqrt(C_1 * C_2) * Sin(deltah / 2);

            double SL = 1 + (0.015 * Math.Pow(avgL - 50, 2)) / Math.Sqrt(20 + Math.Pow(avgL - 50, 2));
            double SC = 1 + 0.045 * avgC_;
            double SH = 1 + 0.015 * avgC_ * T;

            double exp  = Math.Pow((H - 275) / 25, 2);
            double teta = Math.Pow(30, -exp);

            double RC = 2D * Math.Sqrt(Math.Pow(avgC_, 7) / (Math.Pow(avgC_, 7) + p25));
            double RT = -RC *Sin(2 *teta);

            double deltaE = 0;

            deltaE  = Math.Pow(deltaL_ / SL, 2);
            deltaE += Math.Pow(deltaC_ / SC, 2);
            deltaE += Math.Pow(deltaH_ / SH, 2);
            deltaE += RT * (deltaC_ / SC) * (deltaH_ / SH);
            deltaE  = Math.Sqrt(deltaE);

            return(deltaE);
        }