diff options
Diffstat (limited to 'link')
-rwxr-xr-x | link/collink.c | 1422 |
1 files changed, 760 insertions, 662 deletions
diff --git a/link/collink.c b/link/collink.c index 798bc14..3172f2b 100755 --- a/link/collink.c +++ b/link/collink.c @@ -181,6 +181,18 @@ #include "gammap.h" #include "vrml.h" +/* flag usage: + + 0123456789 + . + + abcdefghijklmnopqrstuvwxyz + ....... . .. ....... .. + + ABCDEFGHIJKLMNOPQRSTUVWXYZ + . ....... . . .. .. . +*/ + void usage(char *diag, ...) { int i; fprintf(stderr,"Link ICC profiles, Version %s\n",ARGYLL_VERSION_STR); @@ -211,6 +223,7 @@ void usage(char *diag, ...) { fprintf(stderr," -p absprof Include abstract profile in link\n"); fprintf(stderr," -a file.cal Apply calibration curves to link output and append linear\n"); fprintf(stderr," -H file.cal Append calibration curves to 3dlut\n"); + fprintf(stderr," -O file.cal Use just calibration curves as link and append linear\n"); fprintf(stderr," -s Simple Mode (default)\n"); fprintf(stderr," -g [src.gam] Gamut Mapping Mode [optional source image gamut]\n"); fprintf(stderr," -G [src.gam] Gamut Mapping Mode using inverse outprofile A2B\n"); @@ -219,7 +232,7 @@ void usage(char *diag, ...) { fprintf(stderr," s = saturation, a = absolute colorimetric\n"); fprintf(stderr," -o out_intent p = perceptual, r = relative colorimetric,\n"); fprintf(stderr," s = saturation, a = absolute colorimetric\n"); - fprintf(stderr," Gamut Mapping Mode Options:\n"); + fprintf(stderr," Gamut Mapping Mode Options:\n"); fprintf(stderr," -i intent set linking intent from the following choice:\n"); for (i = 0; ; i++) { icxGMappingIntent gmi; @@ -382,6 +395,8 @@ struct _clink { /* 2 = set MadVR cal1 to cal */ xcal *cal; /* Calibration to apply, NULL if none */ + int calonly; /* calibration curve only - no ICC profile linking */ + /* (We current assume that xyzscale can't be used with gmi) */ double xyzscale; /* < 1.0 if Y is to be scaled in destination XYZ space */ double swxyz[3]; /* Source white point in XYZ */ @@ -1057,559 +1072,568 @@ void devip_devop(void *cntx, double *out, double *in) { #endif } - /* Do DevIn' -> PCS */ - switch(p->in.alg) { - case icmMonoFwdType: { - icxLuMono *lu = (icxLuMono *)p->in.luo; /* Safe to coerce */ + if (p->calonly) { - if (p->in.nocurve) { /* No explicit curve, so do implicit here */ - rv |= lu->fwd_curve(lu, pcsv, win); - rv |= lu->fwd_map(lu, pcsv, pcsv); - } else { - rv |= lu->fwd_map(lu, pcsv, win); + vect_cpy(out, win, p->cal->devchan); + + } else { + + /* Do DevIn' -> PCS */ + switch(p->in.alg) { + case icmMonoFwdType: { + icxLuMono *lu = (icxLuMono *)p->in.luo; /* Safe to coerce */ + + if (p->in.nocurve) { /* No explicit curve, so do implicit here */ + rv |= lu->fwd_curve(lu, pcsv, win); + rv |= lu->fwd_map(lu, pcsv, pcsv); + } else { + rv |= lu->fwd_map(lu, pcsv, win); + } + rv |= lu->fwd_abs(lu, pcsv, pcsv); + break; } - rv |= lu->fwd_abs(lu, pcsv, pcsv); - break; - } - case icmMatrixFwdType: { - icxLuMatrix *lu = (icxLuMatrix *)p->in.luo; /* Safe to coerce */ - icmLuMatrix *plu = (icmLuMatrix *)lu->plu; /* Safe to coerce */ + case icmMatrixFwdType: { + icxLuMatrix *lu = (icxLuMatrix *)p->in.luo; /* Safe to coerce */ + icmLuMatrix *plu = (icmLuMatrix *)lu->plu; /* Safe to coerce */ - if (p->in.nocurve) { /* No explicit curve, so do implicit here */ + if (p->in.nocurve) { /* No explicit curve, so do implicit here */ - if (p->in.tvenc == 8 || p->in.tvenc == 9) { /* xvYCC */ - if (p->in.bt1886) - bt1886_fwd_curve(&p->in.bt, pcsv, win); - else - xvYCC_fwd_curve(pcsv, win); /* Allow for overrange values */ - xvYCC_fwd_matrix(pcsv, pcsv); /* Rec709 primaries */ + if (p->in.tvenc == 8 || p->in.tvenc == 9) { /* xvYCC */ + if (p->in.bt1886) + bt1886_fwd_curve(&p->in.bt, pcsv, win); + else + xvYCC_fwd_curve(pcsv, win); /* Allow for overrange values */ + xvYCC_fwd_matrix(pcsv, pcsv); /* Rec709 primaries */ + } else { + if (p->in.bt1886) + bt1886_fwd_curve(&p->in.bt, pcsv, win); + else + rv |= lu->fwd_curve(lu, pcsv, win); + rv |= lu->fwd_matrix(lu, pcsv, pcsv); + } } else { - if (p->in.bt1886) - bt1886_fwd_curve(&p->in.bt, pcsv, win); + if (p->in.tvenc == 8 || p->in.tvenc == 9) /* xvYCC */ + xvYCC_fwd_matrix(pcsv, pcsv); /* Rec709 primaries */ else - rv |= lu->fwd_curve(lu, pcsv, win); - rv |= lu->fwd_matrix(lu, pcsv, pcsv); + rv |= lu->fwd_matrix(lu, pcsv, win); } - } else { - if (p->in.tvenc == 8 || p->in.tvenc == 9) /* xvYCC */ - xvYCC_fwd_matrix(pcsv, pcsv); /* Rec709 primaries */ - else - rv |= lu->fwd_matrix(lu, pcsv, win); - } #ifdef DEBUG - DEBUGCND printf("After matrix PCS' XYZ %s Lab %s\n",icmPdv(p->in.chan, pcsv), icmPLab(pcsv)); + DEBUGCND printf("After matrix PCS' XYZ %s Lab %s\n",icmPdv(p->in.chan, pcsv), icmPLab(pcsv)); #endif - if (p->in.bt1886) { - bt1886_wp_adjust(&p->in.bt, pcsv, pcsv); + if (p->in.bt1886) { + bt1886_wp_adjust(&p->in.bt, pcsv, pcsv); #ifdef DEBUG - DEBUGCND printf("After bt1886 PCS' XYZ %s Lab %s\n",icmPdv(p->in.chan, pcsv), icmPLab(pcsv)); + DEBUGCND printf("After bt1886 PCS' XYZ %s Lab %s\n",icmPdv(p->in.chan, pcsv), icmPLab(pcsv)); #endif - } + } - rv |= lu->fwd_abs(lu, pcsv, pcsv); + rv |= lu->fwd_abs(lu, pcsv, pcsv); - break; - } - case icmLutType: { - icxLuLut *lu = (icxLuLut *)p->in.luo; /* Safe to coerce */ - if (p->in.nocurve) { /* No explicit curve, so we've got Dev */ - /* Since not PCS, in_abs and matrix cannot be valid, */ - /* so input curve on own is ok to use. */ - rv |= lu->input(lu, pcsv, win); /* Dev -> Dev' */ - rv |= lu->clut(lu, pcsv, pcsv); /* Dev' -> PCS' */ - } else { /* We've got Dev' */ - rv |= lu->clut(lu, pcsv, win); /* Dev' -> PCS' */ + break; } - /* We've got the input profile PCS' at this point. */ + case icmLutType: { + icxLuLut *lu = (icxLuLut *)p->in.luo; /* Safe to coerce */ + if (p->in.nocurve) { /* No explicit curve, so we've got Dev */ + /* Since not PCS, in_abs and matrix cannot be valid, */ + /* so input curve on own is ok to use. */ + rv |= lu->input(lu, pcsv, win); /* Dev -> Dev' */ + rv |= lu->clut(lu, pcsv, pcsv); /* Dev' -> PCS' */ + } else { /* We've got Dev' */ + rv |= lu->clut(lu, pcsv, win); /* Dev' -> PCS' */ + } + /* We've got the input profile PCS' at this point. */ - /* If we're transfering the K value from the input profile to the */ - /* output, copy it into locus[], which will be given to the inverse */ - /* lookup function, else the inverse lookup will generate a K using */ - /* the curve parameters. */ + /* If we're transfering the K value from the input profile to the */ + /* output, copy it into locus[], which will be given to the inverse */ + /* lookup function, else the inverse lookup will generate a K using */ + /* the curve parameters. */ //printf("~1 out.inking = %d\n",p->out.inking); - if (p->out.inking == 0 || p->out.inking == 6) { - if (p->out.locus) { - /* Converts PCS' to K locus proportion */ - lu->clut_locus(lu, locus, pcsv, win); /* Compute possible locus values */ + if (p->out.inking == 0 || p->out.inking == 6) { + if (p->out.locus) { + /* Converts PCS' to K locus proportion */ + lu->clut_locus(lu, locus, pcsv, win); /* Compute possible locus values */ //printf("~1 looked up locus value\n"); - } else { - for (i = 0; i < p->in.chan; i++) /* Target is K input value */ - locus[i] = win[i]; - /* Convert K' to K value ready for aux target */ - if (!p->in.nocurve) { /* we have an input curve, so convert Dev' -> Dev */ - lu->inv_input(lu, locus, locus); - } + } else { + for (i = 0; i < p->in.chan; i++) /* Target is K input value */ + locus[i] = win[i]; + /* Convert K' to K value ready for aux target */ + if (!p->in.nocurve) { /* we have an input curve, so convert Dev' -> Dev */ + lu->inv_input(lu, locus, locus); + } //printf("~1 copied win to locus\n"); - } + } #ifdef DEBUG - DEBUGCND printf("Got possible K %s of %f %f %f %f\n",p->out.locus ? "locus" : "value", locus[0],locus[1],locus[2],locus[3]); + DEBUGCND printf("Got possible K %s of %f %f %f %f\n",p->out.locus ? "locus" : "value", locus[0],locus[1],locus[2],locus[3]); #endif + } + rv |= lu->output(lu, pcsv, pcsv); /* PCS' -> */ + rv |= lu->out_abs(lu, pcsv, pcsv); /* PCS */ + break; } - rv |= lu->output(lu, pcsv, pcsv); /* PCS' -> */ - rv |= lu->out_abs(lu, pcsv, pcsv); /* PCS */ - break; + default: + error("Unexpected algorithm type %d in devip of devip_devop()",p->in.alg); } - default: - error("Unexpected algorithm type %d in devip of devip_devop()",p->in.alg); - } - /* At this point, the PCS is: - * - * If not gamut mapped: - * Lab in the intent selected for the source profile - * If gamut mapped: - * either - * Absolute Lab - * or - * Jab derived from absolute XYZ via the in/out viewing conditions + /* At this point, the PCS is: + * + * If not gamut mapped: + * Lab in the intent selected for the source profile + * If gamut mapped: + * either + * Absolute Lab + * or + * Jab derived from absolute XYZ via the in/out viewing conditions * * and locus[] contains any auxiliar target values if the - * auxiliary is not being created by a rule applied to the PCS. - */ + * auxiliary is not being created by a rule applied to the PCS. + */ - /* - * The order to do this intermediate processing is hard to figure out, - * as is the interaction between such elements. How should the - * abstract profile be properly handled ? - * what should we do if the wphack/rgbbkhack is on and Y scaling is on ? - */ + /* + * The order to do this intermediate processing is hard to figure out, + * as is the interaction between such elements. How should the + * abstract profile be properly handled ? + * what should we do if the wphack/rgbbkhack is on and Y scaling is on ? + */ #ifdef DEBUG - DEBUGCND printf("PCS before map %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]); + DEBUGCND printf("PCS before map %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]); #endif - if (p->wphack) { - int e; - double dd = 0.0; - for (e = 0; e < 3; e++) { /* Does this match the input white point ? */ - double tt; - tt = pcsv[e] - p->in.wp[e]; - dd += tt * tt; - } - dd = sqrt(dd); - - if (dd < 1.0) { /* Triggered withing 1 delta E */ - if (clip == 0) /* Don't count zero's white caused by video input clipping */ - p->wphacked++; - wptrig = 1; - if (p->wphack == 2) { - for (e = 0; e < 3; e++) /* Map input white to given white */ - pcsv[e] = p->hwp[e]; - } else { - for (e = 0; e < 3; e++) /* Map input white to output white */ - pcsv[e] = p->out.wp[e]; + if (p->wphack) { + int e; + double dd = 0.0; + for (e = 0; e < 3; e++) { /* Does this match the input white point ? */ + double tt; + tt = pcsv[e] - p->in.wp[e]; + dd += tt * tt; } + dd = sqrt(dd); + + if (dd < 1.0) { /* Triggered withing 1 delta E */ + if (clip == 0) /* Don't count zero's white caused by video input clipping */ + p->wphacked++; + wptrig = 1; + if (p->wphack == 2) { + for (e = 0; e < 3; e++) /* Map input white to given white */ + pcsv[e] = p->hwp[e]; + } else { + for (e = 0; e < 3; e++) /* Map input white to output white */ + pcsv[e] = p->out.wp[e]; + } #ifndef DEBUG - if (p->verb) + if (p->verb) #endif - { - printf("White point hack mapped %f %f %f to %f %f %f, hit withing %f\n", + { + printf("White point hack mapped %f %f %f to %f %f %f, hit withing %f\n", p->in.wp[0],p->in.wp[1],p->in.wp[2],pcsv[0], pcsv[1], pcsv[2],dd); - fflush(stdout); + fflush(stdout); + } } } - } - /* Do luminence scaling if requested */ - if (wptrig == 0 && p->xyzscale < 1.0) { - double xyz[3]; + /* Do luminence scaling if requested */ + if (wptrig == 0 && p->xyzscale < 1.0) { + double xyz[3]; //printf("~1 got xyzscale = %f\n",p->xyzscale); //printf("PCS %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]); - /* Convert our PCS to XYZ */ - if (p->pcsor == icxSigJabData) { - /* We're being bad in delving inside the xluo, but we'll fix it latter */ - p->out.luo->cam->cam_to_XYZ(p->out.luo->cam, xyz, pcsv); - } else - error("Internal :- not setup to handle Y scaling and non-Jab PCS"); + /* Convert our PCS to XYZ */ + if (p->pcsor == icxSigJabData) { + /* We're being bad in delving inside the xluo, but we'll fix it latter */ + p->out.luo->cam->cam_to_XYZ(p->out.luo->cam, xyz, pcsv); + } else + error("Internal :- not setup to handle Y scaling and non-Jab PCS"); //printf("XYZ %f %f %f\n",xyz[0], xyz[1], xyz[2]); - /* Scale it */ - xyz[0] *= p->xyzscale; - xyz[1] *= p->xyzscale; - xyz[2] *= p->xyzscale; + /* Scale it */ + xyz[0] *= p->xyzscale; + xyz[1] *= p->xyzscale; + xyz[2] *= p->xyzscale; //printf("scaled XYZ %f %f %f\n",xyz[0], xyz[1], xyz[2]); - /* Convert back to PCS */ - if (p->pcsor == icxSigJabData) { - /* We're being bad in delving inside the xluo, but we'll fix it latter */ - p->out.luo->cam->XYZ_to_cam(p->out.luo->cam, pcsv, xyz); - } else - error("Internal :- not setup to handle Y scaling and non-Jab PCS"); + /* Convert back to PCS */ + if (p->pcsor == icxSigJabData) { + /* We're being bad in delving inside the xluo, but we'll fix it latter */ + p->out.luo->cam->XYZ_to_cam(p->out.luo->cam, pcsv, xyz); + } else + error("Internal :- not setup to handle Y scaling and non-Jab PCS"); //printf("scaled PCS %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]); #ifdef DEBUG - DEBUGCND printf("PCS after Y scale %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]); + DEBUGCND printf("PCS after Y scale %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]); #endif - } + } - /* Do gamut mapping */ - if (wptrig == 0 && p->mode > 0 && p->gmi.usemap) { - /* We've used pcsor to ensure PCS space is appropriate */ - - /* Doing XXXK -> XXXK */ - if (p->nhack == 2) { - /* Ideally we would create a 4D PCSK -> PCSK gamut mapping */ - /* to smoothly and accurately cope with the changing source */ - /* and destination gamuts acording to their degree of "K onlyness". */ - /* In practice we're going to simply interpolated between */ - /* two extremes: unrestricted gamut and K only black gamut. */ - double map0[3], map1[3]; - - /* Compute blend of normal gamut map and Konly to Konly gamut map */ - { - p->map->domap(p->map, map0, pcsv); - p->Kmap->domap(p->Kmap, map1, pcsv); - icmBlend3(pcsvm, map0, map1, konlyness); - } + /* Do gamut mapping */ + if (wptrig == 0 && p->mode > 0 && p->gmi.usemap) { + /* We've used pcsor to ensure PCS space is appropriate */ + + /* Doing XXXK -> XXXK */ + if (p->nhack == 2) { + /* Ideally we would create a 4D PCSK -> PCSK gamut mapping */ + /* to smoothly and accurately cope with the changing source */ + /* and destination gamuts acording to their degree of "K onlyness". */ + /* In practice we're going to simply interpolated between */ + /* two extremes: unrestricted gamut and K only black gamut. */ + double map0[3], map1[3]; + + /* Compute blend of normal gamut map and Konly to Konly gamut map */ + { + p->map->domap(p->map, map0, pcsv); + p->Kmap->domap(p->Kmap, map1, pcsv); + icmBlend3(pcsvm, map0, map1, konlyness); + } #ifdef DEBUG - DEBUGCND printf("PCS after map0 %f %f %f map1 %f %f %f\n", map0[0], map0[1], map0[2], map1[0], map1[1], map1[2]); + DEBUGCND printf("PCS after map0 %f %f %f map1 %f %f %f\n", map0[0], map0[1], map0[2], map1[0], map1[1], map1[2]); #endif - /* Normal gamut mapping */ - } else { - { - p->map->domap(p->map, pcsvm, pcsv); + /* Normal gamut mapping */ + } else { + { + p->map->domap(p->map, pcsvm, pcsv); + } } - } #ifdef DEBUG - DEBUGCND printf("PCS after map %f %f %f\n",pcsvm[0], pcsvm[1], pcsvm[2]); + DEBUGCND printf("PCS after map %f %f %f\n",pcsvm[0], pcsvm[1], pcsvm[2]); #endif - } else { - pcsvm[0] = pcsv[0]; - pcsvm[1] = pcsv[1]; - pcsvm[2] = pcsv[2]; - } + } else { + pcsvm[0] = pcsv[0]; + pcsvm[1] = pcsv[1]; + pcsvm[2] = pcsv[2]; + } - /* Gamut mapped PCS value is now in pcsvm[] */ - - /* Abstract profile transform, PCS -> PCS */ - /* pcsor -> abstract -> pcsor conversion */ - /* We're applying any abstract profile after gamut mapping, */ - /* on the assumption is primarily being used to "correct" the */ - /* output device. Ideally the gamut mapping should take the change */ - /* the abstract profile has on the output device into account, but */ - /* currently we're not doing this... */ - if (wptrig == 0 && p->abs_luo != NULL) { - /* Abstract profile is either absolute or relative. */ - /* We need to convert the current PCS into something compatible. */ - /* This is more ugly than it really should be, so we're ignoring it. */ - /* We should really run the source through the abstract profile before */ - /* creating the gamut mapping, to be able to use abstract with gamut */ - /* mapping properly. */ - p->abs_luo->lookup(p->abs_luo, pcsvm, pcsvm); + /* Gamut mapped PCS value is now in pcsvm[] */ + + /* Abstract profile transform, PCS -> PCS */ + /* pcsor -> abstract -> pcsor conversion */ + /* We're applying any abstract profile after gamut mapping, */ + /* on the assumption is primarily being used to "correct" the */ + /* output device. Ideally the gamut mapping should take the change */ + /* the abstract profile has on the output device into account, but */ + /* currently we're not doing this... */ + if (wptrig == 0 && p->abs_luo != NULL) { + /* Abstract profile is either absolute or relative. */ + /* We need to convert the current PCS into something compatible. */ + /* This is more ugly than it really should be, so we're ignoring it. */ + /* We should really run the source through the abstract profile before */ + /* creating the gamut mapping, to be able to use abstract with gamut */ + /* mapping properly. */ + p->abs_luo->lookup(p->abs_luo, pcsvm, pcsvm); #ifdef DEBUG - DEBUGCND printf("PCS after abstract %f %f %f\n",pcsvm[0], pcsvm[1], pcsvm[2]); + DEBUGCND printf("PCS after abstract %f %f %f\n",pcsvm[0], pcsvm[1], pcsvm[2]); #endif - } + } - /* If we're using the existing B2A inking to determine K, */ - /* lookup the output profiles K value for this PCS */ - if (p->mode >= 2 && p->out.inking == 7) { - double tdevv[MAX_CHAN]; + /* If we're using the existing B2A inking to determine K, */ + /* lookup the output profiles K value for this PCS */ + if (p->mode >= 2 && p->out.inking == 7) { + double tdevv[MAX_CHAN]; //printf("~1 dealing with out.inking = %d\n",p->out.inking); - if (p->out.alg != icmLutType || p->out.c->header->colorSpace != icSigCmykData) - error ("Attempting to use non-CMYK output profile to determine K inking"); + if (p->out.alg != icmLutType || p->out.c->header->colorSpace != icSigCmykData) + error ("Attempting to use non-CMYK output profile to determine K inking"); - /* Lookup PCS in B2A of output profile to get target K value */ + /* Lookup PCS in B2A of output profile to get target K value */ //printf("~1 looking up pcs %f %f %f in B2A\n", pcsvm[0], pcsvm[1], pcsvm[2]); - p->out.b2aluo->lookup(p->out.b2aluo, tdevv, pcsvm); + p->out.b2aluo->lookup(p->out.b2aluo, tdevv, pcsvm); //printf("~1 resulting dev %f %f %f %f\n", tdevv[0], tdevv[1], tdevv[2], tdevv[3]); - if (p->out.locus) { - double tpcsv[MAX_CHAN]; - icxLuLut *lu = (icxLuLut *)p->out.luo; /* Safe to coerce */ + if (p->out.locus) { + double tpcsv[MAX_CHAN]; + icxLuLut *lu = (icxLuLut *)p->out.luo; /* Safe to coerce */ - /* Convert PCS to PCS' ready for locus lookup */ - lu->in_abs(lu, tpcsv, pcsvm); - lu->matrix(lu, tpcsv, tpcsv); - lu->input(lu, tpcsv, tpcsv); - lu->clut_locus(lu, locus, tpcsv, tdevv); /* Compute locus values */ - } else { - for (i = 0; i < p->out.chan; i++) /* Target is K value */ - locus[i] = tdevv[i]; - } + /* Convert PCS to PCS' ready for locus lookup */ + lu->in_abs(lu, tpcsv, pcsvm); + lu->matrix(lu, tpcsv, tpcsv); + lu->input(lu, tpcsv, tpcsv); + lu->clut_locus(lu, locus, tpcsv, tdevv); /* Compute locus values */ + } else { + for (i = 0; i < p->out.chan; i++) /* Target is K value */ + locus[i] = tdevv[i]; + } #ifdef DEBUG - DEBUGCND printf("Got possible K %s of %f %f %f %f\n",p->out.locus ? "locus" : "value", locus[0],locus[1],locus[2],locus[3]); + DEBUGCND printf("Got possible K %s of %f %f %f %f\n",p->out.locus ? "locus" : "value", locus[0],locus[1],locus[2],locus[3]); #endif - } + } - /* Do PCS -> DevOut' */ - if (p->nhack == 3 /* All to K only */ - || ntrig /* Neutral or K only to K only hack has triggered */ - || cmytrig /* 100% CMY rough hack has triggered */ - || rgbbktrig) { /* RGB black inpu thas triggered */ - - if (p->nhack == 3 || ntrig) { /* Neutral to K only hack has triggered */ - co pp; - pp.p[0] = pcsvm[0]; /* Input L value */ - p->pcs2k->interp(p->pcs2k, &pp); /* L -> K' */ - if (pp.v[0] < 0.0) /* rspl might have extrapolated */ - pp.v[0] = 0.0; - else if (pp.v[0] > 1.0) - pp.v[0] = 1.0; - out[0] = out[1] = out[2] = 0.0; /* We know output is CMYK' */ - out[3] = pp.v[0]; + /* Do PCS -> DevOut' */ + if (p->nhack == 3 /* All to K only */ + || ntrig /* Neutral or K only to K only hack has triggered */ + || cmytrig /* 100% CMY rough hack has triggered */ + || rgbbktrig) { /* RGB black inpu thas triggered */ + + if (p->nhack == 3 || ntrig) { /* Neutral to K only hack has triggered */ + co pp; + pp.p[0] = pcsvm[0]; /* Input L value */ + p->pcs2k->interp(p->pcs2k, &pp); /* L -> K' */ + if (pp.v[0] < 0.0) /* rspl might have extrapolated */ + pp.v[0] = 0.0; + else if (pp.v[0] > 1.0) + pp.v[0] = 1.0; + out[0] = out[1] = out[2] = 0.0; /* We know output is CMYK' */ + out[3] = pp.v[0]; #ifndef DEBUG - if (p->verb) + if (p->verb) #endif - if (ntrig) { - printf("Neutral hack mapped %s to 0 0 0 %f\n", icmPdv(p->in.chan,win), out[3]); - fflush(stdout); - } - } else if (cmytrig) { /* 100% CMY rough hack has triggered */ - if (cmytrig & 1) { - out[0] = 1.0; - out[1] = out[2] = out[3] = 0.0; - } - if (cmytrig & 2) { - out[1] = 1.0; - out[0] = out[2] = out[3] = 0.0; - } - if (cmytrig & 4) { - out[2] = 1.0; - out[0] = out[1] = out[3] = 0.0; - } + if (ntrig) { + printf("Neutral hack mapped %s to 0 0 0 %f\n", icmPdv(p->in.chan,win), out[3]); + fflush(stdout); + } + } else if (cmytrig) { /* 100% CMY rough hack has triggered */ + if (cmytrig & 1) { + out[0] = 1.0; + out[1] = out[2] = out[3] = 0.0; + } + if (cmytrig & 2) { + out[1] = 1.0; + out[0] = out[2] = out[3] = 0.0; + } + if (cmytrig & 4) { + out[2] = 1.0; + out[0] = out[1] = out[3] = 0.0; + } #ifndef DEBUG - if (p->verb) + if (p->verb) #endif - if (cmytrig != 0) { - if (p->in.chan == 4) - printf("CMY hack mapped %s to %s\n",icmPdv(p->in.chan, win), icmPdv(p->out.chan, out)); - fflush(stdout); + if (cmytrig != 0) { + if (p->in.chan == 4) + printf("CMY hack mapped %s to %s\n",icmPdv(p->in.chan, win), icmPdv(p->out.chan, out)); + fflush(stdout); + } + } else if (rgbbktrig) { + out[0] = out[1] = out[2] = 0.0; } - } else if (rgbbktrig) { - out[0] = out[1] = out[2] = 0.0; - } #ifdef DEBUG - DEBUGCND printf("DevOut' after hack trigger %s\n\n",icmPdv(p->out.chan, out)); + DEBUGCND printf("DevOut' after hack trigger %s\n\n",icmPdv(p->out.chan, out)); #endif - } else { /* Various hacks haven't triggered */ + } else { /* Various hacks haven't triggered */ - switch(p->out.alg) { - case icmMonoBwdType: { - icxLuMono *lu = (icxLuMono *)p->out.luo; /* Safe to coerce */ + switch(p->out.alg) { + case icmMonoBwdType: { + icxLuMono *lu = (icxLuMono *)p->out.luo; /* Safe to coerce */ - rv |= lu->bwd_abs(lu, pcsvm, pcsvm); - rv |= lu->bwd_map(lu, out, pcsvm); - if (p->out.nocurve) { /* No explicit curve, so do implicit here */ - rv |= lu->bwd_curve(lu, out, out); - } - break; - } - case icmMatrixBwdType: { - icxLuMatrix *lu = (icxLuMatrix *)p->out.luo; /* Safe to coerce */ - - rv |= lu->bwd_abs(lu, pcsvm, pcsvm); - rv |= lu->bwd_matrix(lu, out, pcsvm); - if (p->out.nocurve) { /* No explicit curve, so do implicit here */ - rv |= lu->bwd_curve(lu, out, out); + rv |= lu->bwd_abs(lu, pcsvm, pcsvm); + rv |= lu->bwd_map(lu, out, pcsvm); + if (p->out.nocurve) { /* No explicit curve, so do implicit here */ + rv |= lu->bwd_curve(lu, out, out); + } + break; } - break; - } - case icmLutType: { - icxLuLut *lu = (icxLuLut *)p->out.luo; /* Safe to coerce */ + case icmMatrixBwdType: { + icxLuMatrix *lu = (icxLuMatrix *)p->out.luo; /* Safe to coerce */ - if (p->mode < 2) { /* Using B2A table */ - rv |= lu->in_abs(lu, pcsvm, pcsvm); - rv |= lu->matrix(lu, pcsvm, pcsvm); - rv |= lu->input(lu, pcsvm, pcsvm); - rv |= lu->clut(lu, out, pcsvm); + rv |= lu->bwd_abs(lu, pcsvm, pcsvm); + rv |= lu->bwd_matrix(lu, out, pcsvm); if (p->out.nocurve) { /* No explicit curve, so do implicit here */ - rv |= lu->output(lu, out, out); + rv |= lu->bwd_curve(lu, out, out); } + break; + } + case icmLutType: { + icxLuLut *lu = (icxLuLut *)p->out.luo; /* Safe to coerce */ - } else { /* Use inverse A2B table */ - int i; + if (p->mode < 2) { /* Using B2A table */ + rv |= lu->in_abs(lu, pcsvm, pcsvm); + rv |= lu->matrix(lu, pcsvm, pcsvm); + rv |= lu->input(lu, pcsvm, pcsvm); + rv |= lu->clut(lu, out, pcsvm); + if (p->out.nocurve) { /* No explicit curve, so do implicit here */ + rv |= lu->output(lu, out, out); + } + + } else { /* Use inverse A2B table */ + int i; #ifdef USE_MERGE_CLUT_OPT # pragma message("!!!!!!!!!!!! USE_MERGE_CLUT_OPT turned on !!!!!!!!!") - /* Because we have used the ICX_MERGE_CLUT flag, we don't need */ - /* to call inv_out_abs() and inv_output() */ + /* Because we have used the ICX_MERGE_CLUT flag, we don't need */ + /* to call inv_out_abs() and inv_output() */ #else - rv |= lu->inv_out_abs(lu, pcsvm, pcsvm); - rv |= lu->inv_output(lu, pcsvm, pcsvm); + rv |= lu->inv_out_abs(lu, pcsvm, pcsvm); + rv |= lu->inv_output(lu, pcsvm, pcsvm); #endif #ifdef DEBUG - DEBUGCND printf("Calling inv_clut with K aux targets %f %f %f %f and pcsvm %f %f %f %f\n", - locus[0],locus[1],locus[2],locus[3],pcsvm[0],pcsvm[1],pcsvm[2],pcsvm[3]); + DEBUGCND printf("Calling inv_clut with K aux targets %f %f %f %f and pcsvm %f %f %f %f\n", + locus[0],locus[1],locus[2],locus[3],pcsvm[0],pcsvm[1],pcsvm[2],pcsvm[3]); #endif - /* locus[] contains possible K target or locus value, */ - /* so copy it to out[] so that inv_clut will use it. */ - for (i = 0; i < p->out.chan; i++) - out[i] = locus[i]; + /* locus[] contains possible K target or locus value, */ + /* so copy it to out[] so that inv_clut will use it. */ + for (i = 0; i < p->out.chan; i++) + out[i] = locus[i]; - rv |= lu->inv_clut(lu, out, pcsvm); + rv |= lu->inv_clut(lu, out, pcsvm); #ifdef DEBUG - DEBUGCND printf("Got result %f %f %f %f\n", out[0],out[1],out[2],out[3]); + DEBUGCND printf("Got result %f %f %f %f\n", out[0],out[1],out[2],out[3]); #endif - - if (p->out.nocurve) { /* No explicit curve, so do implicit here */ - rv |= lu->inv_input(lu, out, out); + + if (p->out.nocurve) { /* No explicit curve, so do implicit here */ + rv |= lu->inv_input(lu, out, out); + } } + break; } - break; - } - default: - error("Unexpected algorithm type %d in devop of devip_devop()",p->out.alg); - } - if (rv >= 2) - error("icc lookup failed: %d, %s",p->in.c->errc,p->in.c->err); + default: + error("Unexpected algorithm type %d in devop of devip_devop()",p->out.alg); + } + if (rv >= 2) + error("icc lookup failed: %d, %s",p->in.c->errc,p->in.c->err); #ifdef DEBUG - DEBUGCND printf("DevOut' after PCS->Dev %s\n\n",icmPdv(p->out.chan, out)); + DEBUGCND printf("DevOut' after PCS->Dev %s\n\n",icmPdv(p->out.chan, out)); #endif - } + } - if (p->cal != NULL && p->addcal == 1 && p->out.nocurve) { - p->cal->interp(p->cal, out, out); + /* Apply calibration curve */ + if (p->cal != NULL && p->addcal == 1 && p->out.nocurve) { + p->cal->interp(p->cal, out, out); #ifdef DEBUG - DEBUGCND printf("DevOut' after cal curve %s\n\n",icmPdv(p->out.chan, out)); + DEBUGCND printf("DevOut' after cal curve %s\n\n",icmPdv(p->out.chan, out)); #endif - } - - /* Video encode */ - if (p->out.nocurve && p->out.tvenc != 0) { - for (i = 0; i < p->out.chan; i++) { - if (out[i] < 0.0) - out[i] = 0.0; - else if (out[i] > 1.0) - out[i] = 1.0; - } - if (p->out.tvenc == 1) { /* Video 16-235 range */ - icmRGB_2_VidRGB(out, out); - } else if (p->out.tvenc == 3) { /* Rec601 YCbCr */ - icmRec601_RGBd_2_YPbPr(out, out); - icmRecXXX_YPbPr_2_YCbCr(out, out); - } else if (p->out.tvenc == 4) { /* Rec709 1150/60/2:1 YCbCr */ - icmRec709_RGBd_2_YPbPr(out, out); - icmRecXXX_YPbPr_2_YCbCr(out, out); - } else if (p->out.tvenc == 5) { /* Rec709 1250/50/2:1 YCbCr */ - icmRec709_50_RGBd_2_YPbPr(out, out); - icmRecXXX_YPbPr_2_YCbCr(out, out); - } else if (p->out.tvenc == 6) { /* Rec2020 Non-constant Luminance YCbCr encoding */ - icmRec2020_NCL_RGBd_2_YPbPr(out, out); - icmRecXXX_YPbPr_2_YCbCr(out, out); - } else if (p->out.tvenc == 7) { /* Rec2020 Constant Luminance YCbCr encoding */ - icmRec2020_CL_RGBd_2_YPbPr(out, out); - icmRecXXX_YPbPr_2_YCbCr(out, out); } + /* Video encode */ + if (p->out.nocurve && p->out.tvenc != 0) { + for (i = 0; i < p->out.chan; i++) { + if (out[i] < 0.0) + out[i] = 0.0; + else if (out[i] > 1.0) + out[i] = 1.0; + } + if (p->out.tvenc == 1) { /* Video 16-235 range */ + icmRGB_2_VidRGB(out, out); + } else if (p->out.tvenc == 3) { /* Rec601 YCbCr */ + icmRec601_RGBd_2_YPbPr(out, out); + icmRecXXX_YPbPr_2_YCbCr(out, out); + } else if (p->out.tvenc == 4) { /* Rec709 1150/60/2:1 YCbCr */ + icmRec709_RGBd_2_YPbPr(out, out); + icmRecXXX_YPbPr_2_YCbCr(out, out); + } else if (p->out.tvenc == 5) { /* Rec709 1250/50/2:1 YCbCr */ + icmRec709_50_RGBd_2_YPbPr(out, out); + icmRecXXX_YPbPr_2_YCbCr(out, out); + } else if (p->out.tvenc == 6) { /* Rec2020 Non-constant Luminance YCbCr encoding */ + icmRec2020_NCL_RGBd_2_YPbPr(out, out); + icmRecXXX_YPbPr_2_YCbCr(out, out); + } else if (p->out.tvenc == 7) { /* Rec2020 Constant Luminance YCbCr encoding */ + icmRec2020_CL_RGBd_2_YPbPr(out, out); + icmRecXXX_YPbPr_2_YCbCr(out, out); + } + #ifdef NEVER - else if (p->out.tvenc == 8) { /* SD xvYCC with Rec601 YCbCr encoding */ - icmRec601_RGBd_2_YPbPr(out, out); - icmRecXXX_YPbPr_2_YCbCr(out, out); - } else if (p->out.tvenc == 9) { /* HD xvYCC with Rec709 YCbCr encoding */ - icmRec709_RGBd_2_YPbPr(out, out); - icmRecXXX_YPbPr_2_YCbCr(out, out); - } + else if (p->out.tvenc == 8) { /* SD xvYCC with Rec601 YCbCr encoding */ + icmRec601_RGBd_2_YPbPr(out, out); + icmRecXXX_YPbPr_2_YCbCr(out, out); + } else if (p->out.tvenc == 9) { /* HD xvYCC with Rec709 YCbCr encoding */ + icmRec709_RGBd_2_YPbPr(out, out); + icmRecXXX_YPbPr_2_YCbCr(out, out); + } #endif /* NEVER */ #ifdef DEBUG - DEBUGCND printf("DevOut' after TVenc %s\n",icmPdv(p->out.chan, out)); + DEBUGCND printf("DevOut' after TVenc %s\n",icmPdv(p->out.chan, out)); #endif - } + } - if (clip && p->out.nocurve && p->out.tvenc != 0) { + if (clip && p->out.nocurve && p->out.tvenc != 0) { - /* For RGB encoding, unscale +ve clip to preserve hue */ - if (p->out.tvenc == 1) { /* RGB Video 16-235 range */ + /* For RGB encoding, unscale +ve clip to preserve hue */ + if (p->out.tvenc == 1) { /* RGB Video 16-235 range */ - if (!p->in.tvclip && scale > 1.0) { /* We got +ve clipping */ + if (!p->in.tvclip && scale > 1.0) { /* We got +ve clipping */ - /* Re-scale all non-black values */ - for (i = 0; i < 3; i++) { - if (out[i] > (16.0/255.0)) - out[i] = (out[i] - 16.0/255.0) * scale + 16.0/255.0; + /* Re-scale all non-black values */ + for (i = 0; i < 3; i++) { + if (out[i] > (16.0/255.0)) + out[i] = (out[i] - 16.0/255.0) * scale + 16.0/255.0; + } } - } - /* Deal with -ve clipping and sync */ - for (i = 0; i < 3; i++) { - if (clip & (1 << i)) { + /* Deal with -ve clipping and sync */ + for (i = 0; i < 3; i++) { + if (clip & (1 << i)) { - if (full[i] == 0.0) { /* Only extrapolate in black direction */ - double ifull = 1.0 - full[i]; /* Opposite limit to full */ + if (full[i] == 0.0) { /* Only extrapolate in black direction */ + double ifull = 1.0 - full[i]; /* Opposite limit to full */ + + /* Do simple extrapolation (Not perfect though) */ + out[i] = ifull + (out[i] - ifull) * (uci[i] - ifull)/(cin[i] - ifull); + } - /* Do simple extrapolation (Not perfect though) */ - out[i] = ifull + (out[i] - ifull) * (uci[i] - ifull)/(cin[i] - ifull); - } - - /* Clip or pass sync through */ - if (out[i] < 0.0 || out[i] > 1.0 /* clip */ + /* Clip or pass sync through */ + if (out[i] < 0.0 || out[i] > 1.0 /* clip */ #ifdef PRESERVE_SYNC - || fabs(uci[i] - full[i]) < 1e-6 /* or input is at sync level */ + || fabs(uci[i] - full[i]) < 1e-6 /* or input is at sync level */ #endif - ) - out[i] = full[i]; + ) + out[i] = full[i]; + } } - } - /* For YCrCb, do simple linear extrapolation of out of range input. */ - /* (Note we should really change this to preserve hue instead !) */ - } else { - for (i = 0; i < 3; i++) { - if (clip & (1 << i)) { - double ifull = 1.0 - full[i]; /* Opposite limit to full */ - - /* Do simple extrapolation (Not perfect though) */ - out[i] = ifull + (out[i] - ifull) * (uci[i] - ifull)/(cin[i] - ifull); - - if (out[i] < 0.0 || out[i] > 1.0 /* clip */ + /* For YCrCb, do simple linear extrapolation of out of range input. */ + /* (Note we should really change this to preserve hue instead !) */ + } else { + for (i = 0; i < 3; i++) { + if (clip & (1 << i)) { + double ifull = 1.0 - full[i]; /* Opposite limit to full */ + + /* Do simple extrapolation (Not perfect though) */ + out[i] = ifull + (out[i] - ifull) * (uci[i] - ifull)/(cin[i] - ifull); + + if (out[i] < 0.0 || out[i] > 1.0 /* clip */ #ifdef PRESERVE_SYNC - || fabs(uci[i] - full[i]) < 1e-6 /* or input is at sync level */ + || fabs(uci[i] - full[i]) < 1e-6 /* or input is at sync level */ #endif - ) - out[i] = full[i]; + ) + out[i] = full[i]; + } } } - } #ifdef DEBUG - DEBUGCND printf("DevOut' after TVenc un-clip %s\n",icmPdv(p->out.chan, out)); + DEBUGCND printf("DevOut' after TVenc un-clip %s\n",icmPdv(p->out.chan, out)); #endif - } + } - /* For eeColor and Full range RGB, make sure that the cLUT output maps to 1.0 */ - /* The output curve will correct this, irrespective of out.nocurve */ - if (p->tdlut == 1) { /* eeColor encoded input */ - /* ~~ it's not clear if this re-scaling would help with other */ - /* encodings like xvYCC ? */ - if (p->out.tvenc == 0) { /* Full range RGB */ - for (i = 0; i < 3; i++) { - out[i] /= p->coscale[i]; - if (out[i] > 1.0) - out[i] = 1.0; - } + /* For eeColor and Full range RGB, make sure that the cLUT output maps to 1.0 */ + /* The output curve will correct this, irrespective of out.nocurve */ + if (p->tdlut == 1) { /* eeColor encoded input */ + /* ~~ it's not clear if this re-scaling would help with other */ + /* encodings like xvYCC ? */ + if (p->out.tvenc == 0) { /* Full range RGB */ + for (i = 0; i < 3; i++) { + out[i] /= p->coscale[i]; + if (out[i] > 1.0) + out[i] = 1.0; + } #ifdef DEBUG - DEBUGCND printf("DevOut' after eeColor de-scale %s\n\n",icmPdv(p->out.chan, out)); + DEBUGCND printf("DevOut' after eeColor de-scale %s\n\n",icmPdv(p->out.chan, out)); #endif + } } - } - /* lcurve is incompatible with coscale and tvenc ?? */ - if (p->out.lcurve) { /* Apply Y to L* to make output perceptual */ + /* lcurve is incompatible with coscale and tvenc ?? */ + if (p->out.lcurve) { /* Apply Y to L* to make output perceptual */ #ifdef DEBUG - DEBUGCND printf("DevOut' before y2l_curve %s\n\n",icmPdv(p->out.chan, out)); + DEBUGCND printf("DevOut' before y2l_curve %s\n\n",icmPdv(p->out.chan, out)); #endif - y2l_curve(out, out, p->out.lcurve == 2); - } + y2l_curve(out, out, p->out.lcurve == 2); + } #ifdef DEBUG - DEBUGCND printf("DevIn'->DevOut' ret %s\n\n",icmPdv(p->out.chan, out)); + DEBUGCND printf("DevIn'->DevOut' ret %s\n\n",icmPdv(p->out.chan, out)); #endif + } /* Not calonly */ + if (p->verb) { /* Output percent intervals */ int pc; p->count++; @@ -1694,6 +1718,7 @@ void devop_devo(void *cntx, double *out, double *in) { #ifdef DEBUG DEBUGCND printf("After output curve %s\n",icmPdv(p->out.chan, out)); #endif + /* Apply calibration curve */ if (p->cal != NULL && p->addcal == 1) { p->cal->interp(p->cal, out, out); @@ -1711,7 +1736,15 @@ void devop_devo(void *cntx, double *out, double *in) { DEBUGCND printf("After Video encode %s\n",icmPdv(p->out.chan, out)); } #endif + + /* Apply calibration curve */ + } else if (p->calonly && p->cal != NULL && p->addcal == 1) { + p->cal->interp(p->cal, out, out); +#ifdef DEBUG + DEBUGCND printf("After calibration curve %s\n",icmPdv(p->out.chan, out)); +#endif } + #ifdef DEBUG DEBUGCND printf("DevOut'->DevOut ret %s\n",icmPdv(p->out.chan, out)); #endif @@ -1841,13 +1874,13 @@ int write_cube_3DLut(clink *li, icc *icc, char *fname); int main(int argc, char *argv[]) { int fa, nfa, mfa; /* argument we're looking at */ - char in_name[MAXNAMEL+1]; + char in_name[MAXNAMEL+1] = "\000"; char sgam_name[MAXNAMEL+1] = "\000"; /* Source gamut name */ char abs_name[MAXNAMEL+1] = "\000"; /* Abstract profile name */ char cal_name[MAXNAMEL+1] = "\000"; /* Calibration filename */ - char out_name[MAXNAMEL+1]; - char link_name[MAXNAMEL+1]; - char tdlut_name[MAXNAMEL+1]; + char out_name[MAXNAMEL+1] = "\000"; + char link_name[MAXNAMEL+1] = "\000"; + char tdlut_name[MAXNAMEL+1] = "\000"; int verify = 0; /* Do verify pass */ int outinkset = 0; /* The user specfied an output inking */ int intentset = 0; /* The user specified an intent */ @@ -1855,6 +1888,7 @@ main(int argc, char *argv[]) { int modeset = 0; /* The gamut mapping mode was set by the user */ int addcal = 0; /* 1 = Incorporate cal. curves in 3dLUT and set linear MadVR cal1 */ /* 2 = Set 3dLut MadVR cal1 to calibration curves */ + int calonly = 0; /* calibration curve only - no ICC profile linking */ int rv = 0; icxViewCond ivc, ovc; /* Viewing Condition Overrides for in and out profiles */ int ivc_e = -1, ovc_e = -1; /* Enumerated viewing condition */ @@ -1946,7 +1980,7 @@ main(int argc, char *argv[]) { /* Process the arguments */ mfa = 3; /* Minimum final arguments */ - for(fa = 1;fa < argc;fa++) { + for (fa = 1; fa < argc; fa++) { nfa = fa; /* skip to nfa if next argument is used */ if (argv[fa][0] == '-') { /* Look for any flags */ @@ -2100,10 +2134,23 @@ main(int argc, char *argv[]) { /* Calibration curves */ else if (argv[fa][1] == 'a' + || argv[fa][1] == 'O' || argv[fa][1] == 'H') { addcal = 1; if (argv[fa][1] == 'H') addcal = 2; + if (argv[fa][1] == 'O') { + calonly = 1; + + /* Hmm. Make on the fly change to mfa... */ + mfa = 1; + if (na == NULL && (fa+1+mfa) < argc) { + if (argv[fa+1][0] != '-') { + nfa = fa + 1; + na = argv[nfa]; /* next is seperate non-flag argument */ + } + } + } if (na == NULL) usage("Expected calibration filename after -%c",argv[fa][1]); fa = nfa; strncpy(cal_name,na,MAXNAMEL); cal_name[MAXNAMEL] = '\000'; @@ -2577,12 +2624,21 @@ main(int argc, char *argv[]) { } #endif - if (fa >= argc || argv[fa][0] == '-') usage("Missing input profile"); - strncpy(in_name,argv[fa++],MAXNAMEL); in_name[MAXNAMEL] = '\000'; + /* Is this a link created just from a calibration file ? */ + if (calonly) { /* yes */ + li.calonly = calonly; - if (fa >= argc || argv[fa][0] == '-') usage("Missing output profile"); - strncpy(out_name,argv[fa++],MAXNAMEL); out_name[MAXNAMEL] = '\000'; + /* no */ + } else { + /* Get the ICC source & destination profile names */ + if (fa >= argc || argv[fa][0] == '-') usage("Missing input profile"); + strncpy(in_name,argv[fa++],MAXNAMEL); in_name[MAXNAMEL] = '\000'; + + if (fa >= argc || argv[fa][0] == '-') usage("Missing output profile"); + strncpy(out_name,argv[fa++],MAXNAMEL); out_name[MAXNAMEL] = '\000'; + } + /* Get the resulting link profile name */ if (fa >= argc || argv[fa][0] == '-') usage("Missing result profile"); strncpy(link_name,argv[fa++],MAXNAMEL); link_name[MAXNAMEL] = '\000'; @@ -2910,68 +2966,6 @@ main(int argc, char *argv[]) { usage("Can't use 'white point hack' and Luminence scaling intent together"); /* - - - - - - - - - - - - - - - - - - - */ - /* Open up the input device profile for reading, and read header etc. */ - if ((li.in.c = read_embedded_icc(in_name)) == NULL) - error ("Can't open file '%s'",in_name); - li.in.h = li.in.c->header; - - /* Check that it is a suitable device input icc */ - if (li.in.h->deviceClass != icSigInputClass - && li.in.h->deviceClass != icSigDisplayClass - && li.in.h->deviceClass != icSigOutputClass - && li.in.h->deviceClass != icSigColorSpaceClass) /* For sRGB etc. */ - error("Input profile '%s' isn't a device profile",in_name); - - /* Wrap with an expanded icc */ - if ((li.in.x = new_xicc(li.in.c)) == NULL) - error ("Creation of input profile xicc failed"); - - /* Set the default ink limits if not set on command line */ - icxDefaultLimits(li.in.x, &li.in.ink.tlimit, li.in.ink.tlimit, &li.in.ink.klimit, li.in.ink.klimit); - - if (li.verb) { - if (li.in.ink.tlimit >= 0.0) - printf("Input total ink limit assumed is %3.0f%%\n",100.0 * li.in.ink.tlimit); - if (li.in.ink.klimit >= 0.0) - printf("Input black ink limit assumed is %3.0f%%\n",100.0 * li.in.ink.klimit); - } - - /* - - - - - - - - - - - - - - - - - - - */ - /* Open up the abstract profile if requested */ - if (abs_name[0] != '\000') { - if ((li.abs_fp = new_icmFileStd_name(abs_name,"r")) == NULL) - error ("Can't open abstract profile file '%s'",abs_name); - - if ((li.abs_icc = new_icc()) == NULL) - error ("Creation of Abstract profile ICC object failed"); - - /* Read header etc. */ - if ((rv = li.abs_icc->read(li.abs_icc,li.abs_fp,0)) != 0) - error ("%d, %s",rv,li.abs_icc->err); - - if (li.abs_icc->header->deviceClass != icSigAbstractClass) - error("Abstract profile isn't an abstract profile"); - - /* Take intended abstract intent from profile itself */ - if ((li.abs_intent = li.abs_icc->header->renderingIntent) != icAbsoluteColorimetric) - li.abs_intent = icRelativeColorimetric; - - /* Wrap with an expanded icc */ - if ((li.abs_xicc = new_xicc(li.abs_icc)) == NULL) - error ("Creation of abstract profile xicc failed"); - } - /* - - - - - - - - - - - - - - - - - - - */ - /* Open up the output device output profile for reading, and read header etc. */ - if ((li.out.c = read_embedded_icc(out_name)) == NULL) - error ("Can't open file '%s'",out_name); - li.out.h = li.out.c->header; - - if (li.out.h->deviceClass != icSigInputClass - && li.out.h->deviceClass != icSigDisplayClass - && li.out.h->deviceClass != icSigOutputClass - && li.out.h->deviceClass != icSigColorSpaceClass) /* For sRGB etc. */ - error("Output profile isn't a device profile"); - /* Grab the calibration if requested */ if (addcal) { if ((li.cal = new_xcal()) == NULL) @@ -2986,194 +2980,261 @@ main(int argc, char *argv[]) { /* and we don't currently have a way of detecting this */ } - /* Wrap with an expanded icc */ - if ((li.out.x = new_xicc(li.out.c)) == NULL) - error ("Creation of output profile xicc failed"); + if (!calonly) { - /* Set the default ink limits if not set on command line */ - icxDefaultLimits(li.out.x, &li.out.ink.tlimit, li.out.ink.tlimit, &li.out.ink.klimit, li.out.ink.klimit); + /* Open up the input device profile for reading, and read header etc. */ + if ((li.in.c = read_embedded_icc(in_name)) == NULL) + error ("Can't open file '%s'",in_name); + li.in.h = li.in.c->header; - if (li.verb) { - if (li.out.ink.tlimit >= 0.0) - printf("Output total ink limit assumed is %3.0f%%\n",100.0 * li.out.ink.tlimit); - if (li.out.ink.klimit >= 0.0) - printf("Output black ink limit assumed is %3.0f%%\n",100.0 * li.out.ink.klimit); - } + /* Check that it is a suitable device input icc */ + if (li.in.h->deviceClass != icSigInputClass + && li.in.h->deviceClass != icSigDisplayClass + && li.in.h->deviceClass != icSigOutputClass + && li.in.h->deviceClass != icSigColorSpaceClass) /* For sRGB etc. */ + error("Input profile '%s' isn't a device profile",in_name); - /* deal with output black generation. */ - /* Ink limits will have been set in option parsing */ + /* Wrap with an expanded icc */ + if ((li.in.x = new_xicc(li.in.c)) == NULL) + error ("Creation of input profile xicc failed"); - switch (li.out.inking) { - case 0: /* Use input profile K level or locus */ - /* Sanity check */ - if (li.in.h->colorSpace != li.out.h->colorSpace) - error("Can't transfer black ink in & out unless the same colorspaces"); - li.out.ink.k_rule = li.out.locus ? icxKlocus : icxKvalue; /* Given as aux parameter in PCS -> Device */ - break; - case 7: /* Use output profile K level or locus */ - li.out.ink.k_rule = li.out.locus ? icxKlocus : icxKvalue; /* Given as aux parameter in PCS -> Device */ - break; - case 1: /* Minimum K */ - li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; - li.out.ink.c.Kstle = 0.0; - li.out.ink.c.Kstpo = 0.0; - li.out.ink.c.Kenpo = 1.0; - li.out.ink.c.Kenle = 0.0; - li.out.ink.c.Kshap = 1.0; - break; - case 2: /* 0.5 K */ - li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; - li.out.ink.c.Kstle = 0.5; - li.out.ink.c.Kstpo = 0.0; - li.out.ink.c.Kenpo = 1.0; - li.out.ink.c.Kenle = 0.5; - li.out.ink.c.Kshap = 1.0; - break; - case 3: /* Maximum K */ - li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; - li.out.ink.c.Kstle = 1.0; - li.out.ink.c.Kstpo = 0.0; - li.out.ink.c.Kenpo = 1.0; - li.out.ink.c.Kenle = 1.0; - li.out.ink.c.Kshap = 1.0; - break; - case 4: /* Ramp K */ - li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; - li.out.ink.c.Kstle = 0.0; - li.out.ink.c.Kstpo = 0.0; - li.out.ink.c.Kenpo = 1.0; - li.out.ink.c.Kenle = 1.0; - li.out.ink.c.Kshap = 1.0; - break; - case 5: /* Curve */ - li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; - break; /* Other params already set by options */ - case 6: /* Use input profile K locus + dual curve limits */ - /* Sanity check */ - if (li.in.h->colorSpace != li.out.h->colorSpace) - error("Can't transfer black ink in & out unless the same colorspaces"); - li.out.ink.k_rule = li.out.locus ? icxKl5l : icxKl5lk; /* Aux param in PCS -> Device */ - break; /* Other params already set by options */ - } + /* Set the default ink limits if not set on command line */ + icxDefaultLimits(li.in.x, &li.in.ink.tlimit, li.in.ink.tlimit, &li.in.ink.klimit, li.in.ink.klimit); - for (i = 0; i < 2; i++) { - xicc *x; - icxViewCond *v, *vc; - int es; - int *set; - - if (i == 0) { - v = &ivc; /* Override parameters */ - vc = &li.in.vc; /* Target parameters */ - set = &li.in.vc_set; - es = ivc_e; - x = li.in.x; /* xicc */ - } else { - v = &ovc; /* Override parameters */ - vc = &li.out.vc; /* Target parameters */ - set = &li.out.vc_set; - es = ovc_e; - x = li.out.x; /* xicc */ - } - - /* Set the default viewing conditions */ - xicc_enum_viewcond(x, vc, -1, NULL, 0, NULL); - - /* Override the default viewing conditions. */ - /* (?? Could move this code into xicc_enum_viewcond() as an option ??) */ - /* First any enumerated selection */ - if (es != -1) { - if (xicc_enum_viewcond(x, vc, es, NULL, 0, NULL) == -999) - error ("%d, %s",x->errc, x->err); - *set = 1; - } - /* Then any individual paramaters */ - if (v->Ev >= 0) { - vc->Ev = v->Ev; - *set = 1; - } - if (v->Wxyz[0] >= 0.0 && v->Wxyz[1] > 0.0 && v->Wxyz[2] >= 0.0) { - /* Normalise XYZ to current media white */ - vc->Wxyz[0] = v->Wxyz[0]/v->Wxyz[1] * vc->Wxyz[1]; - vc->Wxyz[2] = v->Wxyz[2]/v->Wxyz[1] * vc->Wxyz[1]; - *set = 1; - } - if (v->Wxyz[0] >= 0.0 && v->Wxyz[1] >= 0.0 && v->Wxyz[2] < 0.0) { - /* Convert Yxy to XYZ */ - double x = v->Wxyz[0]; - double y = v->Wxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */ - double z = 1.0 - x - y; - vc->Wxyz[0] = x/y * vc->Wxyz[1]; - vc->Wxyz[2] = z/y * vc->Wxyz[1]; - *set = 1; - } - if (v->La >= 0.0) { - vc->La = v->La; - *set = 1; - } - if (v->Yb >= 0.0) { - vc->Yb = v->Yb; - *set = 1; - } - if (v->Lv >= 0.0) { - vc->Lv = v->Lv; - *set = 1; - } - if (v->Yf >= 0.0) { - vc->Yf = v->Yf; - *set = 1; - } - if (v->Yg >= 0.0) { - vc->Yg = v->Yg; - *set = 1; - } - if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] > 0.0 && v->Gxyz[2] >= 0.0) { - /* Normalise XYZ to current media white */ - vc->Gxyz[0] = v->Gxyz[0]/v->Gxyz[1] * vc->Gxyz[1]; - vc->Gxyz[2] = v->Gxyz[2]/v->Gxyz[1] * vc->Gxyz[1]; - *set = 1; - } - if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] >= 0.0 && v->Gxyz[2] < 0.0) { - /* Convert Yxy to XYZ */ - double x = v->Gxyz[0]; - double y = v->Gxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */ - double z = 1.0 - x - y; - vc->Gxyz[0] = x/y * vc->Gxyz[1]; - vc->Gxyz[2] = z/y * vc->Gxyz[1]; - *set = 1; + if (li.verb) { + if (li.in.ink.tlimit >= 0.0) + printf("Input total ink limit assumed is %3.0f%%\n",100.0 * li.in.ink.tlimit); + if (li.in.ink.klimit >= 0.0) + printf("Input black ink limit assumed is %3.0f%%\n",100.0 * li.in.ink.klimit); } - if (v->hkscale >= 0.0) { - vc->hkscale = v->hkscale; - *set = 1; + /* - - - - - - - - - - - - - - - - - - - */ + /* Open up the abstract profile if requested */ + if (abs_name[0] != '\000') { + if ((li.abs_fp = new_icmFileStd_name(abs_name,"r")) == NULL) + error ("Can't open abstract profile file '%s'",abs_name); + + if ((li.abs_icc = new_icc()) == NULL) + error ("Creation of Abstract profile ICC object failed"); + + /* Read header etc. */ + if ((rv = li.abs_icc->read(li.abs_icc,li.abs_fp,0)) != 0) + error ("%d, %s",rv,li.abs_icc->err); + + if (li.abs_icc->header->deviceClass != icSigAbstractClass) + error("Abstract profile isn't an abstract profile"); + + /* Take intended abstract intent from profile itself */ + if ((li.abs_intent = li.abs_icc->header->renderingIntent) != icAbsoluteColorimetric) + li.abs_intent = icRelativeColorimetric; + + /* Wrap with an expanded icc */ + if ((li.abs_xicc = new_xicc(li.abs_icc)) == NULL) + error ("Creation of abstract profile xicc failed"); } - if (v->mtaf >= 0.0) { - vc->mtaf = v->mtaf; - *set = 1; + /* - - - - - - - - - - - - - - - - - - - */ + /* Open up the output device output profile for reading, and read header etc. */ + if ((li.out.c = read_embedded_icc(out_name)) == NULL) + error ("Can't open file '%s'",out_name); + li.out.h = li.out.c->header; + + if (li.out.h->deviceClass != icSigInputClass + && li.out.h->deviceClass != icSigDisplayClass + && li.out.h->deviceClass != icSigOutputClass + && li.out.h->deviceClass != icSigColorSpaceClass) /* For sRGB etc. */ + error("Output profile isn't a device profile"); + + /* Wrap with an expanded icc */ + if ((li.out.x = new_xicc(li.out.c)) == NULL) + error ("Creation of output profile xicc failed"); + + /* Set the default ink limits if not set on command line */ + icxDefaultLimits(li.out.x, &li.out.ink.tlimit, li.out.ink.tlimit, &li.out.ink.klimit, li.out.ink.klimit); + + if (li.verb) { + if (li.out.ink.tlimit >= 0.0) + printf("Output total ink limit assumed is %3.0f%%\n",100.0 * li.out.ink.tlimit); + if (li.out.ink.klimit >= 0.0) + printf("Output black ink limit assumed is %3.0f%%\n",100.0 * li.out.ink.klimit); } - if (v->Wxyz2[0] >= 0.0 && v->Wxyz2[1] > 0.0 && v->Wxyz2[2] >= 0.0) { - /* Normalise XYZ */ - vc->Wxyz2[0] = v->Wxyz2[0]/v->Wxyz2[1] * vc->Wxyz2[1]; - vc->Wxyz2[2] = v->Wxyz2[2]/v->Wxyz2[1] * vc->Wxyz2[1]; - *set = 1; + + /* deal with output black generation. */ + /* Ink limits will have been set in option parsing */ + + switch (li.out.inking) { + case 0: /* Use input profile K level or locus */ + /* Sanity check */ + if (li.in.h->colorSpace != li.out.h->colorSpace) + error("Can't transfer black ink in & out unless the same colorspaces"); + li.out.ink.k_rule = li.out.locus ? icxKlocus : icxKvalue; /* Given as aux parameter in PCS -> Device */ + break; + case 7: /* Use output profile K level or locus */ + li.out.ink.k_rule = li.out.locus ? icxKlocus : icxKvalue; /* Given as aux parameter in PCS -> Device */ + break; + case 1: /* Minimum K */ + li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; + li.out.ink.c.Kstle = 0.0; + li.out.ink.c.Kstpo = 0.0; + li.out.ink.c.Kenpo = 1.0; + li.out.ink.c.Kenle = 0.0; + li.out.ink.c.Kshap = 1.0; + break; + case 2: /* 0.5 K */ + li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; + li.out.ink.c.Kstle = 0.5; + li.out.ink.c.Kstpo = 0.0; + li.out.ink.c.Kenpo = 1.0; + li.out.ink.c.Kenle = 0.5; + li.out.ink.c.Kshap = 1.0; + break; + case 3: /* Maximum K */ + li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; + li.out.ink.c.Kstle = 1.0; + li.out.ink.c.Kstpo = 0.0; + li.out.ink.c.Kenpo = 1.0; + li.out.ink.c.Kenle = 1.0; + li.out.ink.c.Kshap = 1.0; + break; + case 4: /* Ramp K */ + li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; + li.out.ink.c.Kstle = 0.0; + li.out.ink.c.Kstpo = 0.0; + li.out.ink.c.Kenpo = 1.0; + li.out.ink.c.Kenle = 1.0; + li.out.ink.c.Kshap = 1.0; + break; + case 5: /* Curve */ + li.out.ink.k_rule = li.out.locus ? icxKluma5 : icxKluma5k; + break; /* Other params already set by options */ + case 6: /* Use input profile K locus + dual curve limits */ + /* Sanity check */ + if (li.in.h->colorSpace != li.out.h->colorSpace) + error("Can't transfer black ink in & out unless the same colorspaces"); + li.out.ink.k_rule = li.out.locus ? icxKl5l : icxKl5lk; /* Aux param in PCS -> Device */ + break; /* Other params already set by options */ } - if (v->Wxyz2[0] >= 0.0 && v->Wxyz2[1] >= 0.0 && v->Wxyz2[2] < 0.0) { - /* Convert Yxy to XYZ */ - double x = v->Wxyz2[0]; - double y = v->Wxyz2[1]; /* If Y == 1.0, then X+Y+Z = 1/y */ - double z = 1.0 - x - y; - vc->Wxyz2[0] = x/y * vc->Wxyz2[1]; - vc->Wxyz2[2] = z/y * vc->Wxyz2[1]; - *set = 1; + + /* Deal with source & dest viewing conditions */ + for (i = 0; i < 2; i++) { + xicc *x; + icxViewCond *v, *vc; + int es; + int *set; + + if (i == 0) { + v = &ivc; /* Override parameters */ + vc = &li.in.vc; /* Target parameters */ + set = &li.in.vc_set; + es = ivc_e; + x = li.in.x; /* xicc */ + } else { + v = &ovc; /* Override parameters */ + vc = &li.out.vc; /* Target parameters */ + set = &li.out.vc_set; + es = ovc_e; + x = li.out.x; /* xicc */ + } + + /* Set the default viewing conditions */ + xicc_enum_viewcond(x, vc, -1, NULL, 0, NULL); + + /* Override the default viewing conditions. */ + /* (?? Could move this code into xicc_enum_viewcond() as an option ??) */ + /* First any enumerated selection */ + if (es != -1) { + if (xicc_enum_viewcond(x, vc, es, NULL, 0, NULL) == -999) + error ("%d, %s",x->errc, x->err); + *set = 1; + } + /* Then any individual paramaters */ + if (v->Ev >= 0) { + vc->Ev = v->Ev; + *set = 1; + } + if (v->Wxyz[0] >= 0.0 && v->Wxyz[1] > 0.0 && v->Wxyz[2] >= 0.0) { + /* Normalise XYZ to current media white */ + vc->Wxyz[0] = v->Wxyz[0]/v->Wxyz[1] * vc->Wxyz[1]; + vc->Wxyz[2] = v->Wxyz[2]/v->Wxyz[1] * vc->Wxyz[1]; + *set = 1; + } + if (v->Wxyz[0] >= 0.0 && v->Wxyz[1] >= 0.0 && v->Wxyz[2] < 0.0) { + /* Convert Yxy to XYZ */ + double x = v->Wxyz[0]; + double y = v->Wxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */ + double z = 1.0 - x - y; + vc->Wxyz[0] = x/y * vc->Wxyz[1]; + vc->Wxyz[2] = z/y * vc->Wxyz[1]; + *set = 1; + } + if (v->La >= 0.0) { + vc->La = v->La; + *set = 1; + } + if (v->Yb >= 0.0) { + vc->Yb = v->Yb; + *set = 1; + } + if (v->Lv >= 0.0) { + vc->Lv = v->Lv; + *set = 1; + } + if (v->Yf >= 0.0) { + vc->Yf = v->Yf; + *set = 1; + } + if (v->Yg >= 0.0) { + vc->Yg = v->Yg; + *set = 1; + } + if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] > 0.0 && v->Gxyz[2] >= 0.0) { + /* Normalise XYZ to current media white */ + vc->Gxyz[0] = v->Gxyz[0]/v->Gxyz[1] * vc->Gxyz[1]; + vc->Gxyz[2] = v->Gxyz[2]/v->Gxyz[1] * vc->Gxyz[1]; + *set = 1; + } + if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] >= 0.0 && v->Gxyz[2] < 0.0) { + /* Convert Yxy to XYZ */ + double x = v->Gxyz[0]; + double y = v->Gxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */ + double z = 1.0 - x - y; + vc->Gxyz[0] = x/y * vc->Gxyz[1]; + vc->Gxyz[2] = z/y * vc->Gxyz[1]; + *set = 1; + } + + if (v->hkscale >= 0.0) { + vc->hkscale = v->hkscale; + *set = 1; + } + if (v->mtaf >= 0.0) { + vc->mtaf = v->mtaf; + *set = 1; + } + if (v->Wxyz2[0] >= 0.0 && v->Wxyz2[1] > 0.0 && v->Wxyz2[2] >= 0.0) { + /* Normalise XYZ */ + vc->Wxyz2[0] = v->Wxyz2[0]/v->Wxyz2[1] * vc->Wxyz2[1]; + vc->Wxyz2[2] = v->Wxyz2[2]/v->Wxyz2[1] * vc->Wxyz2[1]; + *set = 1; + } + if (v->Wxyz2[0] >= 0.0 && v->Wxyz2[1] >= 0.0 && v->Wxyz2[2] < 0.0) { + /* Convert Yxy to XYZ */ + double x = v->Wxyz2[0]; + double y = v->Wxyz2[1]; /* If Y == 1.0, then X+Y+Z = 1/y */ + double z = 1.0 - x - y; + vc->Wxyz2[0] = x/y * vc->Wxyz2[1]; + vc->Wxyz2[2] = z/y * vc->Wxyz2[1]; + *set = 1; + } } - } + + } /* Not calonly */ if (li.verb) printf("Configured options\n"); /* - - - - - - - - - - - - - - - - - - - */ /* Setup the profile color lookup information */ - { + if (!calonly) { icmLuAlgType oalg; /* Native output algorithm */ icColorSpaceSignature natpcs; /* Underlying native output PCS */ int flb = 0, fl = 0; /* luobj flags */ @@ -3542,9 +3603,23 @@ main(int argc, char *argv[]) { } /* - - - - - - - - - - - - - - - - - - - */ - /* Sanity checking */ + if (calonly) { /* Fudge the in & out settings */ + li.in.csp = li.cal->colspace; + li.in.chan = li.cal->devchan; + li.in.nocurve = 1; + li.in.lcurve = 0; + li.in.bt1886 = 0; - if (li.cal != NULL) { + li.out.csp = li.cal->colspace; + li.out.chan = li.cal->devchan; + li.out.nocurve = 1; + li.out.lcurve = 0; + li.out.bt1886 = 0; + + li.mode = 0; /* Simple mode */ + + /* Sanity checking */ + } else if (li.cal != NULL) { if (li.cal->colspace != li.out.csp) { error("Calibration space %s doesn't match output profile %s", icm2str(icmColorSpaceSignature, li.cal->colspace), @@ -3905,12 +3980,14 @@ main(int argc, char *argv[]) { if (li.in.tvenc >= 3) { wh->colorSpace = icSigYCbCrData; /* Use YCbCr encoding */ } else { - wh->colorSpace = li.in.h->colorSpace; /* Input profile device space */ +// wh->colorSpace = li.in.h->colorSpace; /* Input profile device space */ + wh->colorSpace = li.in.csp; /* Input profile device space */ } if (li.out.tvenc >= 3) { wh->pcs = icSigYCbCrData; /* Use YCbCr encoding */ } else { - wh->pcs = li.out.h->colorSpace; /* Output profile device space */ +// wh->pcs = li.out.h->colorSpace; /* Output profile device space */ + wh->pcs = li.out.csp; /* Output profile device space */ } if (li.mode > 0) { wh->renderingIntent = li.gmi.icci; /* Closest ICC intent */ @@ -4009,8 +4086,21 @@ main(int argc, char *argv[]) { wo->allocate((icmBase *)wo);/* Allocate space */ strcpy(wo->desc, dst); /* Copy the string in */ } + /* ProfileSequenceDescTag: */ - { + if (li.calonly) { /* Fake one up */ + unsigned int i; + icmProfileSequenceDesc *wo; + if ((wo = (icmProfileSequenceDesc *)wr_icc->add_tag( + wr_icc, icSigProfileSequenceDescTag, icSigProfileSequenceDescType)) == NULL) + return 1; + + wo->count = 2; /* Number of descriptions in sequence */ + if (wo->allocate((icmBase *)wo) != 0) /* Allocate space for all the DescStructures */ + error("allocate failed: %d, %s",wr_icc->errc,wr_icc->err); + + /* Real one */ + } else { unsigned int i; icmProfileSequenceDesc *wo; if ((wo = (icmProfileSequenceDesc *)wr_icc->add_tag( @@ -4107,7 +4197,7 @@ main(int argc, char *argv[]) { } } /* ColorantTable: */ - { + if (!li.calonly) { int i; unsigned int j; int repclip = 0; @@ -4560,8 +4650,10 @@ main(int argc, char *argv[]) { #endif /* USE_APXLS */ 0, &li, /* Context */ - li.in.h->colorSpace, /* Input color space */ - li.out.h->colorSpace, /* Output color space */ +// li.in.h->colorSpace, /* Input color space */ + li.in.csp, /* Input color space */ +// li.out.h->colorSpace, /* Output color space */ + li.out.csp, /* Output color space */ devi_devip, /* Input transfer tables devi->devi' */ NULL, NULL, /* Use default input colorspace range */ devip_devop, /* devi' -> devo' transfer function */ @@ -4840,15 +4932,21 @@ main(int argc, char *argv[]) { li.cal->del(li.cal); } - li.in.luo->del(li.in.luo); - li.in.x->del(li.in.x); - li.in.c->del(li.in.c); + if (li.in.luo != NULL) + li.in.luo->del(li.in.luo); + if (li.in.x != NULL) + li.in.x->del(li.in.x); + if (li.in.c != NULL) + li.in.c->del(li.in.c); if (li.out.b2aluo != NULL) li.out.b2aluo->del(li.out.b2aluo); - li.out.luo->del(li.out.luo); - li.out.x->del(li.out.x); - li.out.c->del(li.out.c); + if (li.out.luo != NULL) + li.out.luo->del(li.out.luo); + if (li.out.x != NULL) + li.out.x->del(li.out.x); + if (li.out.c != NULL) + li.out.c->del(li.out.c); return 0; } |