Feature: colprof -u (Structured JSON Calculation Progress) #13
@@ -2700,6 +2700,10 @@ White &nb
|
|||||||
useful in creating a profile for a device that is known to have a
|
useful in creating a profile for a device that is known to have a
|
||||||
perfectly linear response, such as a camera in RAW mode.<br>
|
perfectly linear response, such as a camera in RAW mode.<br>
|
||||||
<br>
|
<br>
|
||||||
|
<a name="u_progress"></a> <span style="font-weight: bold;">-u:</span>
|
||||||
|
Emit structured JSON progress events to <tt>stdout</tt> during profile
|
||||||
|
calculation (e.g. <tt>{"event": "progress", "stage": "gamut_mapping", "percent": 75}</tt>).<br>
|
||||||
|
<br>
|
||||||
<a name="u"></a> <span style="font-weight: bold;">-u:</span> Input
|
<a name="u"></a> <span style="font-weight: bold;">-u:</span> Input
|
||||||
profiles will normally be created such that the white patch of the
|
profiles will normally be created such that the white patch of the
|
||||||
test chart will be mapped to perfect white when used with any of the
|
test chart will be mapped to perfect white when used with any of the
|
||||||
|
|||||||
+14
-4
@@ -75,6 +75,14 @@
|
|||||||
|
|
||||||
#define DEMPH_DEFAULT 1.0 /* Default dark region emphasis == none */
|
#define DEMPH_DEFAULT 1.0 /* Default dark region emphasis == none */
|
||||||
|
|
||||||
|
int json_progress = 0;
|
||||||
|
|
||||||
|
void emit_json_progress(const char *stage, int percent) {
|
||||||
|
if (!json_progress) return;
|
||||||
|
printf("{\"event\": \"progress\", \"stage\": \"%s\", \"percent\": %d}\n", stage, percent);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Flags used:
|
Flags used:
|
||||||
@@ -129,6 +137,7 @@ void usage(char *diag, ...) {
|
|||||||
fprintf(stderr," X = display XYZ cLUT + matrix, Y = display XYZ cLUT + debug matrix\n");
|
fprintf(stderr," X = display XYZ cLUT + matrix, Y = display XYZ cLUT + debug matrix\n");
|
||||||
fprintf(stderr," g = gamma+matrix, s = shaper+matrix, m = matrix only,\n");
|
fprintf(stderr," g = gamma+matrix, s = shaper+matrix, m = matrix only,\n");
|
||||||
fprintf(stderr," G = single gamma+matrix, S = single shaper+matrix\n");
|
fprintf(stderr," G = single gamma+matrix, S = single shaper+matrix\n");
|
||||||
|
fprintf(stderr," -u Emit structured JSON calculation progress to stdout\n");
|
||||||
fprintf(stderr," -u If input profile, auto scale WP to allow extrapolation\n");
|
fprintf(stderr," -u If input profile, auto scale WP to allow extrapolation\n");
|
||||||
fprintf(stderr," -ua If input profile, force absolute intent\n");
|
fprintf(stderr," -ua If input profile, force absolute intent\n");
|
||||||
fprintf(stderr," -uc If input profile, clip cLUT values above WP\n");
|
fprintf(stderr," -uc If input profile, clip cLUT values above WP\n");
|
||||||
@@ -492,8 +501,6 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (argv[fa][1] == 'u') {
|
else if (argv[fa][1] == 'u') {
|
||||||
autowpsc = 1;
|
|
||||||
clipovwp = 0;
|
|
||||||
if (argv[fa][2] == 'a') {
|
if (argv[fa][2] == 'a') {
|
||||||
autowpsc = 2;
|
autowpsc = 2;
|
||||||
clipovwp = 0;
|
clipovwp = 0;
|
||||||
@@ -502,12 +509,15 @@ int main(int argc, char *argv[]) {
|
|||||||
clipovwp = 1;
|
clipovwp = 1;
|
||||||
} else if (argv[fa][2] != '\000') {
|
} else if (argv[fa][2] != '\000') {
|
||||||
usage("Unknown flag '%c' after -u",argv[fa][2]);
|
usage("Unknown flag '%c' after -u",argv[fa][2]);
|
||||||
|
} else if (na != NULL && (isdigit(na[0]) || (na[0] == '.' && isdigit(na[1])))) {
|
||||||
} else if (na != NULL) {
|
|
||||||
fa = nfa;
|
fa = nfa;
|
||||||
iwpscale = atof(na);
|
iwpscale = atof(na);
|
||||||
if (iwpscale < 0.0 || iwpscale > 200.0)
|
if (iwpscale < 0.0 || iwpscale > 200.0)
|
||||||
usage("Argument '%s' to flag -u out of range",na);
|
usage("Argument '%s' to flag -u out of range",na);
|
||||||
|
autowpsc = 1;
|
||||||
|
clipovwp = 0;
|
||||||
|
} else {
|
||||||
|
json_progress = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Clip primaries */
|
/* Clip primaries */
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ typedef enum {
|
|||||||
prof_matonly = 7 /* XYZ matrix, linear */
|
prof_matonly = 7 /* XYZ matrix, linear */
|
||||||
} prof_atype;
|
} prof_atype;
|
||||||
|
|
||||||
|
extern int json_progress;
|
||||||
|
void emit_json_progress(const char *stage, int percent);
|
||||||
|
|
||||||
/* Output or Display device */
|
/* Output or Display device */
|
||||||
void make_output_icc(
|
void make_output_icc(
|
||||||
prof_atype ptype, /* Profile output type */
|
prof_atype ptype, /* Profile output type */
|
||||||
|
|||||||
+15
-5
@@ -229,14 +229,19 @@ void in_b2a_clut(void *cntx, double *out, double in[3]
|
|||||||
DBG(("convert PCS' to DEV' got %f %f %f %f\n",out[0],out[1],out[2],out[3]))
|
DBG(("convert PCS' to DEV' got %f %f %f %f\n",out[0],out[1],out[2],out[3]))
|
||||||
DBG(("in_b2a_clut returning DEV' %f %f %f\n",out[0],out[1],out[2]))
|
DBG(("in_b2a_clut returning DEV' %f %f %f\n",out[0],out[1],out[2]))
|
||||||
|
|
||||||
if (p->verb
|
if ((p->verb || json_progress)
|
||||||
&& tn == 0
|
&& tn == 0
|
||||||
) { /* Output percent intervals */
|
) { /* Output percent intervals */
|
||||||
int pc;
|
int pc;
|
||||||
p->count++;
|
p->count++;
|
||||||
pc = (int)(p->count * 100.0/p->total + 0.5);
|
pc = (int)(p->count * 100.0/p->total + 0.5);
|
||||||
if (pc != p->last) {
|
if (pc != p->last) {
|
||||||
printf("%c%2d%%",cr_char,pc); fflush(stdout);
|
if (p->verb) {
|
||||||
|
printf("%c%2d%%",cr_char,pc); fflush(stdout);
|
||||||
|
}
|
||||||
|
if (json_progress) {
|
||||||
|
emit_json_progress("b2a_table", pc);
|
||||||
|
}
|
||||||
p->last = pc;
|
p->last = pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1171,7 +1176,7 @@ make_input_icc(
|
|||||||
|
|
||||||
/* We now setup an exact inverse, colorimetric style */
|
/* We now setup an exact inverse, colorimetric style */
|
||||||
/* Use helper function to do the hard work. */
|
/* Use helper function to do the hard work. */
|
||||||
if (cx.verb) {
|
if (cx.verb || json_progress) {
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
int extra;
|
int extra;
|
||||||
cx.count = 0;
|
cx.count = 0;
|
||||||
@@ -1182,8 +1187,13 @@ make_input_icc(
|
|||||||
for (extra = 1, ui = 0; ui < 3; extra *= (blut_clutPoints[ui++]-1))
|
for (extra = 1, ui = 0; ui < 3; extra *= (blut_clutPoints[ui++]-1))
|
||||||
;
|
;
|
||||||
cx.total += extra;
|
cx.total += extra;
|
||||||
printf("Creating B to A tables\n");
|
if (cx.verb) {
|
||||||
printf(" 0%%"); fflush(stdout);
|
printf("Creating B to A tables\n");
|
||||||
|
printf(" 0%%"); fflush(stdout);
|
||||||
|
}
|
||||||
|
if (json_progress) {
|
||||||
|
emit_json_progress("b2a_table", 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wr_icco->create_lut_xforms(
|
if (wr_icco->create_lut_xforms(
|
||||||
|
|||||||
+49
-15
@@ -431,12 +431,17 @@ void in_a2b_clut(void *cntx, double out[3], double *in, int itn) {
|
|||||||
}
|
}
|
||||||
DBG(("convert PCS to PCS' got %f %f %f\n",out[0],out[1],out[2]))
|
DBG(("convert PCS to PCS' got %f %f %f\n",out[0],out[1],out[2]))
|
||||||
|
|
||||||
if (p->verb && itn == 0) { /* Output percent intervals */
|
if ((p->verb || json_progress) && itn == 0) { /* Output percent intervals */
|
||||||
int pc;
|
int pc;
|
||||||
p->count++;
|
p->count++;
|
||||||
pc = (int)(p->count * 100.0/p->total + 0.5);
|
pc = (int)(p->count * 100.0/p->total + 0.5);
|
||||||
if (pc != p->last) {
|
if (pc != p->last) {
|
||||||
printf("%c%2d%%",cr_char,pc); fflush(stdout);
|
if (p->verb) {
|
||||||
|
printf("%c%2d%%",cr_char,pc); fflush(stdout);
|
||||||
|
}
|
||||||
|
if (json_progress) {
|
||||||
|
emit_json_progress("a2b_table", pc);
|
||||||
|
}
|
||||||
p->last = pc;
|
p->last = pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -658,12 +663,17 @@ void out_b2a_clut(void *cntx, double *out, double in[3], int itn) {
|
|||||||
|
|
||||||
DBG(("out_b2a_clut returning DEV' %s\n",icmPdv(p->ochan, out)))
|
DBG(("out_b2a_clut returning DEV' %s\n",icmPdv(p->ochan, out)))
|
||||||
|
|
||||||
if (p->verb && itn == 0) { /* Output percent intervals */
|
if ((p->verb || json_progress) && itn == 0) { /* Output percent intervals */
|
||||||
int pc;
|
int pc;
|
||||||
p->count++;
|
p->count++;
|
||||||
pc = (int)(p->count * 100.0/p->total + 0.5);
|
pc = (int)(p->count * 100.0/p->total + 0.5);
|
||||||
if (pc != p->last) {
|
if (pc != p->last) {
|
||||||
printf("%c%2d%%",cr_char,pc); fflush(stdout);
|
if (p->verb) {
|
||||||
|
printf("%c%2d%%",cr_char,pc); fflush(stdout);
|
||||||
|
}
|
||||||
|
if (json_progress) {
|
||||||
|
emit_json_progress("b2a_table", pc);
|
||||||
|
}
|
||||||
p->last = pc;
|
p->last = pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -728,12 +738,17 @@ static void PCSp_bdist(void *cntx, double out[1], double in[3], int tn
|
|||||||
out[0] = (gdist + 20.0)/40.0;
|
out[0] = (gdist + 20.0)/40.0;
|
||||||
//printf("~1 bdist returning %f\n",out[0]);
|
//printf("~1 bdist returning %f\n",out[0]);
|
||||||
|
|
||||||
if (p->verb) { /* Output percent intervals */
|
if (p->verb || json_progress) { /* Output percent intervals */
|
||||||
int pc;
|
int pc;
|
||||||
p->count++;
|
p->count++;
|
||||||
pc = (int)(p->count * 100.0/p->total + 0.5);
|
pc = (int)(p->count * 100.0/p->total + 0.5);
|
||||||
if (pc != p->last) {
|
if (pc != p->last) {
|
||||||
printf("%c%2d%%",cr_char,pc); fflush(stdout);
|
if (p->verb) {
|
||||||
|
printf("%c%2d%%",cr_char,pc); fflush(stdout);
|
||||||
|
}
|
||||||
|
if (json_progress) {
|
||||||
|
emit_json_progress("gamut_table", pc);
|
||||||
|
}
|
||||||
p->last = pc;
|
p->last = pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2551,6 +2566,7 @@ make_output_icc(
|
|||||||
if (csgamp == NULL) {
|
if (csgamp == NULL) {
|
||||||
if (verb)
|
if (verb)
|
||||||
printf(" Finding Source Colorspace Perceptual Gamut\n");
|
printf(" Finding Source Colorspace Perceptual Gamut\n");
|
||||||
|
emit_json_progress("gamut_mapping", 10);
|
||||||
|
|
||||||
if ((csgamp = cx.ixp->get_gamut(cx.ixp, gres)) == NULL)
|
if ((csgamp = cx.ixp->get_gamut(cx.ixp, gres)) == NULL)
|
||||||
error ("%d, %s",src_xicc->e.c, src_xicc->e.m);
|
error ("%d, %s",src_xicc->e.c, src_xicc->e.m);
|
||||||
@@ -2567,6 +2583,7 @@ make_output_icc(
|
|||||||
|
|
||||||
if (verb)
|
if (verb)
|
||||||
printf(" Finding Source Colorspace Saturation Gamut\n");
|
printf(" Finding Source Colorspace Saturation Gamut\n");
|
||||||
|
emit_json_progress("gamut_mapping", 25);
|
||||||
|
|
||||||
if ((csgams = ixs->get_gamut(ixs, gres)) == NULL)
|
if ((csgams = ixs->get_gamut(ixs, gres)) == NULL)
|
||||||
error ("%d, %s",src_xicc->e.c, src_xicc->e.m);
|
error ("%d, %s",src_xicc->e.c, src_xicc->e.m);
|
||||||
@@ -2614,6 +2631,7 @@ make_output_icc(
|
|||||||
/* Creat the destination gamut surface */
|
/* Creat the destination gamut surface */
|
||||||
if (verb)
|
if (verb)
|
||||||
printf(" Finding Destination Gamut\n");
|
printf(" Finding Destination Gamut\n");
|
||||||
|
emit_json_progress("gamut_mapping", 40);
|
||||||
|
|
||||||
if ((ogam = cx.ox->get_gamut(cx.ox, gres)) == NULL)
|
if ((ogam = cx.ox->get_gamut(cx.ox, gres)) == NULL)
|
||||||
error ("%d, %s",wr_xicc->e.c, wr_xicc->e.m);
|
error ("%d, %s",wr_xicc->e.c, wr_xicc->e.m);
|
||||||
@@ -2657,6 +2675,7 @@ make_output_icc(
|
|||||||
|
|
||||||
if (verb)
|
if (verb)
|
||||||
printf(" Creating Gamut match\n");
|
printf(" Creating Gamut match\n");
|
||||||
|
emit_json_progress("gamut_mapping", 75);
|
||||||
|
|
||||||
/* The real range of Lab 0..100,-128..128,1-28..128 cube */
|
/* The real range of Lab 0..100,-128..128,1-28..128 cube */
|
||||||
/* when mapped to CAM is ridiculously large (ie. */
|
/* when mapped to CAM is ridiculously large (ie. */
|
||||||
@@ -2673,6 +2692,7 @@ make_output_icc(
|
|||||||
);
|
);
|
||||||
if (cx.pmap == NULL)
|
if (cx.pmap == NULL)
|
||||||
error ("Failed to make perceptual gamut map transform");
|
error ("Failed to make perceptual gamut map transform");
|
||||||
|
emit_json_progress("gamut_mapping", 100);
|
||||||
|
|
||||||
|
|
||||||
if (sepsat) {
|
if (sepsat) {
|
||||||
@@ -2784,7 +2804,7 @@ make_output_icc(
|
|||||||
for (i = 0; i < cx.ochan; i++)
|
for (i = 0; i < cx.ochan; i++)
|
||||||
a2bgres[i] = a2bres;
|
a2bgres[i] = a2bres;
|
||||||
|
|
||||||
if (cx.verb) {
|
if (cx.verb || json_progress) {
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
int extra;
|
int extra;
|
||||||
cx.count = 0;
|
cx.count = 0;
|
||||||
@@ -2797,9 +2817,13 @@ make_output_icc(
|
|||||||
;
|
;
|
||||||
cx.total += extra;
|
cx.total += extra;
|
||||||
#endif
|
#endif
|
||||||
printf("Creating inverse gamut mapped A to B tables\n");
|
if (cx.verb) {
|
||||||
|
printf("Creating inverse gamut mapped A to B tables\n");
|
||||||
printf(" 0%%"); fflush(stdout);
|
printf(" 0%%"); fflush(stdout);
|
||||||
|
}
|
||||||
|
if (json_progress) {
|
||||||
|
emit_json_progress("a2b_table", 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_IGM_ONE
|
#ifdef DEBUG_IGM_ONE
|
||||||
@@ -2879,7 +2903,7 @@ make_output_icc(
|
|||||||
/* for perceptual and saturation intents */
|
/* for perceptual and saturation intents */
|
||||||
/* Use helper function to do the hard work. */
|
/* Use helper function to do the hard work. */
|
||||||
|
|
||||||
if (cx.verb) {
|
if (cx.verb || json_progress) {
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
int extra;
|
int extra;
|
||||||
cx.count = 0;
|
cx.count = 0;
|
||||||
@@ -2892,8 +2916,13 @@ make_output_icc(
|
|||||||
;
|
;
|
||||||
cx.total += extra;
|
cx.total += extra;
|
||||||
#endif
|
#endif
|
||||||
printf("Creating B to A tables\n");
|
if (cx.verb) {
|
||||||
printf(" 0%%"); fflush(stdout);
|
printf("Creating B to A tables\n");
|
||||||
|
printf(" 0%%"); fflush(stdout);
|
||||||
|
}
|
||||||
|
if (json_progress) {
|
||||||
|
emit_json_progress("b2a_table", 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_ONE
|
#ifdef DEBUG_ONE
|
||||||
@@ -3137,13 +3166,18 @@ make_output_icc(
|
|||||||
for (i = 0; i < cx.ichan; i++)
|
for (i = 0; i < cx.ichan; i++)
|
||||||
clutres[i] = b2ares;
|
clutres[i] = b2ares;
|
||||||
|
|
||||||
if (cx.verb) {
|
if (cx.verb || json_progress) {
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
cx.count = 0;
|
cx.count = 0;
|
||||||
cx.last = -1;
|
cx.last = -1;
|
||||||
for (cx.total = 1, ui = 0; ui < cx.ichan; cx.total *= clutres[ui++])
|
for (cx.total = 1, ui = 0; ui < cx.ichan; cx.total *= clutres[ui++])
|
||||||
;
|
;
|
||||||
printf(" 0%%"); fflush(stdout);
|
if (cx.verb) {
|
||||||
|
printf(" 0%%"); fflush(stdout);
|
||||||
|
}
|
||||||
|
if (json_progress) {
|
||||||
|
emit_json_progress("gamut_table", 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8917,7 +8917,7 @@ static void calc_ocent(rspl *s) {
|
|||||||
|
|
||||||
/* Hmm. This isn't very reliable in detecting failure. */
|
/* Hmm. This isn't very reliable in detecting failure. */
|
||||||
if (ctx.oog)
|
if (ctx.oog)
|
||||||
printf("calc_ocent failed to return in-gamut focal point!\n");
|
warning("calc_ocent failed to return in-gamut focal point!");
|
||||||
|
|
||||||
//printf("Final angle = %f\n", ctx.ret);
|
//printf("Final angle = %f\n", ctx.ret);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user