diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-09-01 13:56:46 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2014-09-01 13:56:46 +0200 |
commit | 22f703cab05b7cd368f4de9e03991b7664dc5022 (patch) | |
tree | 6f4d50beaa42328e24b1c6b56b6ec059e4ef21a5 /icc/testDE2K.c |
Initial import of argyll version 1.5.1-8debian/1.5.1-8
Diffstat (limited to 'icc/testDE2K.c')
-rw-r--r-- | icc/testDE2K.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/icc/testDE2K.c b/icc/testDE2K.c new file mode 100644 index 0000000..11a4201 --- /dev/null +++ b/icc/testDE2K.c @@ -0,0 +1,226 @@ + +/* Test the CIE delta E 2000 code */ + +#include <stdio.h> +#include <math.h> +#include "icc.h" + + +/* Reference data */ + +#define NTESTS 34 + +/* From the Sharma, Wu and Dalal "Implementation Notes" etc. paper: */ +struct { + double Lab1[3]; + double Lab2[3]; + double de; +} ref[NTESTS] = { + { 50.0000, 2.6772, -79.7751, 50.0000, 0.0000, -82.7485, 2.0425 }, + { 50.0000, 3.1571, -77.2803, 50.0000, 0.0000, -82.7485, 2.8615 }, + { 50.0000, 2.8361, -74.0200, 50.0000, 0.0000, -82.7485, 3.4412 }, + { 50.0000, -1.3802, -84.2814, 50.0000, 0.0000, -82.7485, 1.0000 }, + { 50.0000, -1.1848, -84.8006, 50.0000, 0.0000, -82.7485, 1.0000 }, + { 50.0000, -0.9009, -85.5211, 50.0000, 0.0000, -82.7485, 1.0000 }, + { 50.0000, 0.0000, 0.0000, 50.0000, -1.0000, 2.0000, 2.3669 }, + { 50.0000, -1.0000, 2.0000, 50.0000, 0.0000, 0.0000, 2.3669 }, + { 50.0000, 2.4900, -0.0010, 50.0000, -2.4900, 0.0009, 7.1792 }, + { 50.0000, 2.4900, -0.0010, 50.0000, -2.4900, 0.0010, 7.1792 }, + { 50.0000, 2.4900, -0.0010, 50.0000, -2.4900, 0.0011, 7.2195 }, + { 50.0000, 2.4900, -0.0010, 50.0000, -2.4900, 0.0012, 7.2195 }, + { 50.0000, -0.0010, 2.4900, 50.0000, 0.0009, -2.4900, 4.8045 }, + { 50.0000, -0.0010, 2.4900, 50.0000, 0.0010, -2.4900, 4.8045 }, + { 50.0000, -0.0010, 2.4900, 50.0000, 0.0011, -2.4900, 4.7461 }, + { 50.0000, 2.5000, 0.0000, 50.0000, 0.0000, -2.5000, 4.3065 }, + { 50.0000, 2.5000, 0.0000, 73.0000, 25.0000, -18.0000, 27.1492 }, + { 50.0000, 2.5000, 0.0000, 61.0000, -5.0000, 29.0000, 22.8977 }, + { 50.0000, 2.5000, 0.0000, 56.0000, -27.0000, -3.0000, 31.9030 }, + { 50.0000, 2.5000, 0.0000, 58.0000, 24.0000, 15.0000, 19.4535 }, + { 50.0000, 2.5000, 0.0000, 50.0000, 3.1736, 0.5854, 1.0000 }, + { 50.0000, 2.5000, 0.0000, 50.0000, 3.2972, 0.0000, 1.0000 }, + { 50.0000, 2.5000, 0.0000, 50.0000, 1.8634, 0.5757, 1.0000 }, + { 50.0000, 2.5000, 0.0000, 50.0000, 3.2592, 0.3350, 1.0000 }, + { 60.2574, -34.0099, 36.2677, 60.4626, -34.1751, 39.4387, 1.2644 }, + { 63.0109, -31.0961, -5.8663, 62.8187, -29.7946, -4.0864, 1.2630 }, + { 61.2901, 3.7196, -5.3901, 61.4292, 2.2480, -4.9620, 1.8731 }, + { 35.0831, -44.1164, 3.7933, 35.0232, -40.0716, 1.5901, 1.8645 }, + { 22.7233, 20.0904, -46.6940, 23.0331, 14.9730, -42.5619, 2.0373 }, + { 36.4612, 47.8580, 18.3852, 36.2715, 50.5065, 21.2231, 1.4146 }, + { 90.8027, -2.0831, 1.4410, 91.1528, -1.6435, 0.0447, 1.4441 }, + { 90.9257, -0.5406, -0.9208, 88.6381, -0.8985, -0.7239, 1.5381 }, + { 6.7747, -0.2908, -2.4247, 5.8714, -0.0985, -2.2286, 0.6377 }, + { 2.0776, 0.0795, -1.1350, 0.9033, -0.0636, -0.5514, 0.9082 } +}; + +double icmCIE2K(double *Lab1, double *Lab2); + +int main(void) { + int rv = 0; + int i; + + printf("Starting Test:\n"); + +#ifdef NEVER + for (i = 0; i < NTESTS; i++) { + printf("Lab1 = %f %f %f\n", ref[i].Lab1[0], ref[i].Lab1[1], ref[i].Lab1[2]); + printf("Lab2 = %f %f %f\n", ref[i].Lab2[0], ref[i].Lab2[1], ref[i].Lab2[2]); + printf("de = %f\n",ref[i].de); + } +#endif + + /* Test it all out */ + for (i = 0; i < NTESTS; i++) { + double de; + + de = icmCIE2K(ref[i].Lab1, ref[i].Lab2); + if (fabs(de - ref[i].de) > 0.0001) { + printf("Error at index %d:\n",i); + printf("Lab1 = %f %f %f\n", ref[i].Lab1[0], ref[i].Lab1[1], ref[i].Lab1[2]); + printf("Lab2 = %f %f %f\n", ref[i].Lab2[0], ref[i].Lab2[1], ref[i].Lab2[2]); + printf("DeltaE is %f, should be %f\n\n",de,ref[i].de); + rv = 1; + } + de = icmCIE2K(ref[i].Lab2, ref[i].Lab1); + if (fabs(de - ref[i].de) > 0.0001) { + printf("Error at index %d:\n",i); + printf("Lab1 = %f %f %f\n", ref[i].Lab2[0], ref[i].Lab2[1], ref[i].Lab2[2]); + printf("Lab2 = %f %f %f\n", ref[i].Lab1[0], ref[i].Lab1[1], ref[i].Lab1[2]); + printf("DeltaE is %f, should be %f\n\n",de,ref[i].de); + rv = 1; + } + } + + printf("Test Finished\n"); + return rv; +} + +#ifdef NEVER /* Test implementation in icc.c */ + +/* From the paper "The CIEDE2000 Color-Difference Formula: Implementation Notes, */ +/* Supplementary Test Data, and Mathematical Observations", by */ +/* Gaurav Sharma, Wencheng Wu and Edul N. Dalal, */ +/* Color Res. Appl., vol. 30, no. 1, pp. 21-30, Feb. 2005. */ + +/* Return the CIEDE2000 Delta E color difference measure squared, for two Lab values */ +double icmCIE2Ksq(double *Lab0, double *Lab1) { + double C1, C2; + double h1, h2; + double dL, dC, dH; + double dsq; + + /* The trucated value of PI is needed to ensure that the */ + /* test cases pass, as one of them lies on the edge of */ + /* a mathematical discontinuity. The precision is still */ + /* enough for any practical use. */ +#define RAD2DEG(xx) (180.0/3.14159265358979 * (xx)) +#define DEG2RAD(xx) (3.14159265358979/180.0 * (xx)) + + /* Compute Cromanance and Hue angles */ + { + double C1ab, C2ab; + double Cab, Cab7, G; + double a1, a2; + + C1ab = sqrt(Lab0[1] * Lab0[1] + Lab0[2] * Lab0[2]); + C2ab = sqrt(Lab1[1] * Lab1[1] + Lab1[2] * Lab1[2]); + Cab = 0.5 * (C1ab + C2ab); + Cab7 = pow(Cab,7.0); + G = 0.5 * (1.0 - sqrt(Cab7/(Cab7 + 6103515625.0))); + a1 = (1.0 + G) * Lab0[1]; + a2 = (1.0 + G) * Lab1[1]; + C1 = sqrt(a1 * a1 + Lab0[2] * Lab0[2]); + C2 = sqrt(a2 * a2 + Lab1[2] * Lab1[2]); + + if (C1 < 1e-9) + h1 = 0.0; + else { + h1 = RAD2DEG(atan2(Lab0[2], a1)); + if (h1 < 0.0) + h1 += 360.0; + } + + if (C2 < 1e-9) + h2 = 0.0; + else { + h2 = RAD2DEG(atan2(Lab1[2], a2)); + if (h2 < 0.0) + h2 += 360.0; + } + } + + /* Compute delta L, C and H */ + { + double dh; + + dL = Lab1[0] - Lab0[0]; + dC = C2 - C1; + if (C1 < 1e-9 || C2 < 1e-9) { + dh = 0.0; + } else { + dh = h2 - h1; + if (dh > 180.0) + dh -= 360.0; + else if (dh < -180.0) + dh += 360.0; + } + + dH = 2.0 * sqrt(C1 * C2) * sin(DEG2RAD(0.5 * dh)); + } + + { + double L, C, h, T; + double hh, ddeg; + double C7, RC, L50sq, SL, SC, SH, RT; + double dLsq, dCsq, dHsq, RCH; + + L = 0.5 * (Lab0[0] + Lab1[0]); + C = 0.5 * (C1 + C2); + if (C1 < 1e-9 || C2 < 1e-9) { + h = h1 + h2; + } else { + h = h1 + h2; + if (fabs(h1 - h2) > 180.0) { + if (h < 360.0) + h += 360.0; + else if (h >= 360.0) + h -= 360.0; + } + h *= 0.5; + } + T = 1.0 - 0.17 * cos(DEG2RAD(h-30.0)) + 0.24 * cos(DEG2RAD(2.0 * h)) + + 0.32 * cos(DEG2RAD(3.0 * h + 6.0)) - 0.2 * cos(DEG2RAD(4.0 * h - 63.0)); + hh = (h - 275.0)/25.0; + ddeg = 30.0 * exp(-hh * hh); + C7 = pow(C,7.0); + RC = 2.0 * sqrt(C7/(C7 + 6103515625.0)); + L50sq = (L - 50.0) * (L - 50.0); + SL = 1.0 + (0.015 * L50sq)/sqrt(20.0 + L50sq); + SC = 1.0 + 0.045 * C; + SH = 1.0 + 0.015 * C * T; + RT = -sin(DEG2RAD(2 * ddeg)) * RC; + + dLsq = dL/SL; + dCsq = dC/SC; + dHsq = dH/SH; + + RCH = RT * dCsq * dHsq; + + dLsq *= dLsq; + dCsq *= dCsq; + dHsq *= dHsq; + + dsq = dLsq + dCsq + dHsq + RCH; + } + + return dsq; + +#undef RAD2DEG +#undef DEG2RAD +} + +/* Return the CIE2DE000 Delta E color difference measure for two Lab values */ +double icmCIE2K(double *Lab0, double *Lab1) { + return sqrt(icmCIE2Ksq(Lab0, Lab1)); +} + +#endif /* NEVER */ |