diff --git a/doc/profcheck.html b/doc/profcheck.html index 44445ef..627aa42 100755 --- a/doc/profcheck.html +++ b/doc/profcheck.html @@ -22,6 +22,8 @@ 1), 2 to print each DE
+  -u             Emit + structured JSON Delta E report to stdout
 -c              Show @@ -233,6 +235,12 @@ Sort be .ti3 PCS values

+ The -u flag causes the final delta E check report to be + emitted to stdout in structured JSON format (e.g., + {"event": "report", "peak_de2000": 2.34, "avg_de2000": 0.51, "rms": 0.61}). + This facilitates subprocess integration and mathematical extraction of error + metrics without parsing human-readable text.
+
The -c option causes the differences between the test values and the profile prediction of the color for each device value to be displayed in CIE94 delta E, rather than plain L*a*b* delta E. CIE94 diff --git a/profile/profcheck.c b/profile/profcheck.c index 33f6756..f7fb848 100644 --- a/profile/profcheck.c +++ b/profile/profcheck.c @@ -55,6 +55,7 @@ usage(void) { fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n"); fprintf(stderr,"usage: profcheck [-options] data.ti3 iccprofile.icm\n"); fprintf(stderr," -v [level] Verbosity level (default 1), 2 to print each DE\n"); + fprintf(stderr," -u Emit structured JSON Delta E report to stdout\n"); fprintf(stderr," -c Show CIE94 delta E values\n"); fprintf(stderr," -k Show CIEDE2000 delta E values\n"); fprintf(stderr," -w create %s visualisation (iccprofile%s)\n",vrml_format(),vrml_ext()); @@ -105,6 +106,7 @@ typedef struct { int main(int argc, char *argv[]) { int fa,nfa; /* current argument we're looking at */ int verb = 0; + int json_report = 0; int cie94 = 0; int cie2k = 0; int dovrml = 0; @@ -187,6 +189,11 @@ int main(int argc, char *argv[]) { } } + /* JSON Delta E report */ + else if (argv[fa][1] == 'u') { + json_report = 1; + } + /* VRML/X3D */ else if (argv[fa][1] == 'w') dovrml = 1; @@ -1246,8 +1253,23 @@ int main(int argc, char *argv[]) { wrl->make_lines_vc(wrl, 0, 0.0); wrl->del(wrl); } - printf("Profile check complete, errors%s: max. = %f, avg. = %f, RMS = %f\n", - cie2k ? "(CIEDE2000)" : cie94 ? " (CIE94)" : "", merr, aerr/nsamps, sqrt(rerr/nsamps)); + if (json_report) { + if (cie2k) { + printf("{\"event\": \"report\", \"peak_de2000\": %.2f, \"avg_de2000\": %.2f, \"rms\": %.2f}\n", + merr, aerr/nsamps, sqrt(rerr/nsamps)); + } else if (cie94) { + printf("{\"event\": \"report\", \"peak_de94\": %.2f, \"avg_de94\": %.2f, \"rms\": %.2f}\n", + merr, aerr/nsamps, sqrt(rerr/nsamps)); + } else { + printf("{\"event\": \"report\", \"peak_de\": %.2f, \"avg_de\": %.2f, \"rms\": %.2f}\n", + merr, aerr/nsamps, sqrt(rerr/nsamps)); + } + fflush(stdout); + } + if (verb || !json_report) { + printf("Profile check complete, errors%s: max. = %f, avg. = %f, RMS = %f\n", + cie2k ? "(CIEDE2000)" : cie94 ? " (CIE94)" : "", merr, aerr/nsamps, sqrt(rerr/nsamps)); + } /* ------------------------------- */ /* If we want sort by target value */