/* Our main loop. */ void imb_Lab2LCh( float *p, float *q, int n ) { int x; for( x = 0; x < n; x++ ) { float L = p[0]; float a = p[1]; float b = p[2]; float C, h; p += 3; C = sqrt( a * a + b * b ); h = im_col_ab2h( a, b ); q[0] = L; q[1] = C; q[2] = h; q += 3; } }
/** * im_col_dE00: * @L1: Input coordinate 1 * @a1: Input coordinate 1 * @b1: Input coordinate 1 * @L2: Input coordinate 2 * @a2: Input coordinate 2 * @b2: Input coordinate 2 * * CIEDE2000, from: * * Luo, Cui, Rigg, "The Development of the CIE 2000 Colour-Difference * Formula: CIEDE2000", COLOR research and application, pp 340 * * Returns: CIE dE2000 colour difference. */ float im_col_dE00( float L1, float a1, float b1, float L2, float a2, float b2 ) { /* Code if you want XYZ params and the colour temp used in the reference float im_col_dE00( float X1, float Y1, float Z1, float X2, float Y2, float Z2 ) { const double X0 = 94.811; const double Y0 = 100.0; const double Z0 = 107.304; #define f(I) ((I) > 0.008856 ? \ cbrt( (I), 1.0 / 3.0 ) : 7.7871 * (I) + (16.0 / 116.0)) double nX1 = f( X1 / X0 ); double nY1 = f( Y1 / Y0 ); double nZ1 = f( Z1 / Z0 ); double L1 = 116 * nY1 - 16; double a1 = 500 * (nX1 - nY1); double b1 = 200 * (nY1 - nZ1); double nX2 = f( X2 / X0 ); double nY2 = f( Y2 / Y0 ); double nZ2 = f( Z2 / Z0 ); double L2 = 116 * nY2 - 16; double a2 = 500 * (nX2 - nY2); double b2 = 200 * (nY2 - nZ2); */ /* Chroma and mean chroma (C bar) */ double C1 = sqrt( a1 * a1 + b1 * b1 ); double C2 = sqrt( a2 * a2 + b2 * b2 ); double Cb = (C1 + C2) / 2; /* G */ double Cb7 = Cb * Cb * Cb * Cb * Cb * Cb * Cb; double G = 0.5 * (1 - sqrt( Cb7 / (Cb7 + pow( 25, 7 )) )); /* L', a', b', C', h' */ double L1d = L1; double a1d = (1 + G) * a1; double b1d = b1; double C1d = sqrt( a1d * a1d + b1d * b1d ); double h1d = im_col_ab2h( a1d, b1d ); double L2d = L2; double a2d = (1 + G) * a2; double b2d = b2; double C2d = sqrt( a2d * a2d + b2d * b2d ); double h2d = im_col_ab2h( a2d, b2d ); /* L' bar, C' bar, h' bar */ double Ldb = (L1d + L2d) / 2; double Cdb = (C1d + C2d) / 2; double hdb = fabs( h1d - h2d ) < 180 ? (h1d + h2d) / 2 : fabs( h1d + h2d - 360 ) / 2; /* dtheta, RC */ double hdbd = (hdb - 275) / 25; double dtheta = 30 * exp( -(hdbd * hdbd) ); double Cdb7 = Cdb * Cdb * Cdb * Cdb * Cdb * Cdb * Cdb; double RC = 2 * sqrt( Cdb7 / (Cdb7 + pow( 25, 7 )) ); /* RT, T. */ double RT = -sin( IM_RAD( 2 * dtheta ) ) * RC; double T = 1 - 0.17 * cos( IM_RAD( hdb - 30 ) ) + 0.24 * cos( IM_RAD( 2 * hdb ) ) + 0.32 * cos( IM_RAD( 3 * hdb + 6 ) ) - 0.20 * cos( IM_RAD( 4 * hdb - 63 ) ); /* SL, SC, SH */ double Ldb50 = Ldb - 50; double SL = 1 + (0.015 * Ldb50 * Ldb50) / sqrt( 20 + Ldb50 * Ldb50); double SC = 1 + 0.045 * Cdb; double SH = 1 + 0.015 * Cdb * T; /* hue difference ... careful! */ double dhd = fabs( h1d - h2d ) < 180 ? h1d - h2d : 360 - (h1d - h2d); /* dLd, dCd dHd */ double dLd = L1d - L2d; double dCd = C1d - C2d; double dHd = 2 * sqrt( C1d * C2d ) * sin( IM_RAD( dhd / 2 ) ); /* Parametric factors for viewing parameters. */ const double kL = 1.0; const double kC = 1.0; const double kH = 1.0; /* Normalised terms. */ double nL = dLd / (kL * SL); double nC = dCd / (kC * SC); double nH = dHd / (kH * SH); /* dE00!! */ double dE00 = sqrt( nL * nL + nC * nC + nH * nH + RT * nC * nH ); /* printf( "X1 = %g, Y1 = %g, Z1 = %g\n", X1, Y1, Z1 ); printf( "X2 = %g, Y2 = %g, Z2 = %g\n", X2, Y2, Z2 ); printf( "L1 = %g, a1 = %g, b1 = %g\n", L1, a1, b1 ); printf( "L2 = %g, a2 = %g, b2 = %g\n", L2, a2, b2 ); printf( "L1d = %g, a1d = %g, b1d = %g, C1d = %g, h1d = %g\n", L1d, a1d, b1d, C1d, h1d ); printf( "L2d = %g, a2d = %g, b2d = %g, C2d = %g, h2d = %g\n", L2d, a2d, b2d, C2d, h2d ); printf( "G = %g, T = %g, SL = %g, SC = %g, SH = %g, RT = %g\n", G, T, SL, SC, SH, RT ); printf( "dE00 = %g\n", dE00 ); */ return( dE00 ); }