diff options
Diffstat (limited to 'xicc/xlut.c')
-rw-r--r-- | xicc/xlut.c | 73 |
1 files changed, 50 insertions, 23 deletions
diff --git a/xicc/xlut.c b/xicc/xlut.c index 21c286e..bbad934 100644 --- a/xicc/xlut.c +++ b/xicc/xlut.c @@ -56,8 +56,8 @@ do anything useful though, the chromatic adapation tag would have to be used for absolute intent. This may be the way of improving compatibility with other systems, - but would break compatibility with existing Argyll profiles, - unless special measures are taken: + and is needed for V4, but would break compatibility with existing + Argyll profiles, unless special measures are taken: ie. @@ -65,7 +65,7 @@ Create Bradford chromatic adapation matrix and store it in tag Adapt all the readings using Bradford Create white point and store it in tag (white point will be D50) - Adapt all the readings to the white point using wrong Von-Kries (no change) + Adapt all the readings to the white point using wrong Von-Kries (== NOOP) Store relative colorimetric cLUT Set version >= 2.4 @@ -154,12 +154,16 @@ #undef DISABLE_KCURVE_FILTER /* [Undef] don't filter the Kcurve */ #undef REPORT_LOCUS_SEGMENTS /* [Undef[ Examine how many segments there are in aux inversion */ +#define XYZ_EXTRA_SMOOTH 20.0 /* Extra smoothing factor for XYZ profiles */ #define SHP_SMOOTH 1.0 /* Input shaper curve smoothing */ #define OUT_SMOOTH1 1.0 /* Output shaper curve smoothing for L*, X,Y,Z */ #define OUT_SMOOTH2 1.0 /* Output shaper curve smoothing for a*, b* */ #define CAMCLIPTRANS 1.0 /* [1.0] Cam clipping transition region Delta E */ -#define USECAMCLIPSPLINE /* [def] use spline blend */ + /* Should this be smaller ? */ +#undef USECAMCLIPSPLINE /* [Und] use spline blend between PCS and Jab */ + +#define CCJSCALE 2.0 /* [2.0] Amount to emphasize J delta E in in computing clip */ /* * TTBD: @@ -1322,6 +1326,7 @@ double *in /* Function input values to invert (== clut output' values) */ if (crv && clipd != NULL) { + /* Compute the clip DE */ for (cdist = 0.0, f = 0; f < fdi; f++) { double tt; @@ -1329,6 +1334,7 @@ double *in /* Function input values to invert (== clut output' values) */ cdist += tt * tt; } cdist = sqrt(cdist); + DBR(("Targ PCS %f %f %f Clipped %f %f %f cdist %f\n",tin[0],tin[1],tin[2],pp[0].v[0],pp[0].v[1],pp[0].v[2],cdist)) } nsoln &= RSPL_NOSOLNS; /* Get number of solutions */ @@ -1368,6 +1374,7 @@ double *in /* Function input values to invert (== clut output' values) */ for (f = 0; f < fdi; f++) /* Transfer CAM targ */ cpp.v[f] = tin[f]; + cpp.v[0] *= CCJSCALE; /* Make sure that the auxiliar value is initialized, */ /* even though it shouldn't have any effect, since should clipp. */ @@ -1376,7 +1383,6 @@ double *in /* Function input values to invert (== clut output' values) */ cpp.p[e] = 0.5; } } - if (p->clutTable->di > fdi) { /* ie. CMYK->Lab, there will be ambiguity */ nsoln = p->cclutTable->rev_interp( @@ -1404,12 +1410,14 @@ double *in /* Function input values to invert (== clut output' values) */ } /* Compute the CAM clip distances */ + cpp.v[0] /= CCJSCALE; for (cdist = 0.0, f = 0; f < fdi; f++) { double tt; tt = cpp.v[f] - tin[f]; cdist += tt * tt; } cdist = sqrt(cdist); + DBR(("Targ CAM %f %f %f Clipped %f %f %f cdist %f\n",tin[0],tin[1],tin[2],cpp.v[0],cpp.v[1],cpp.v[2],cdist)) /* Use magic number to set blend distance, and compute a blend factor. */ /* Blend over 1 delta E, otherwise the Lab & CAM02 divergence can result */ @@ -1425,20 +1433,21 @@ double *in /* Function input values to invert (== clut output' values) */ /* Blend between solution values for PCS and CAM clip result. */ /* We're hoping that the solutions are close, and expect them to be */ /* that way when we're close to the gamut surface (since the cell */ - /* vertex values should be exact, irrespective of which space they're */ - /* in), but weird things could happen away from the surface. Weird */ - /* things can happen anyway with "clip to nearest", since this is not */ + /* vertex values should be exact, irrespective of which interpolation */ + /* space they're in), but weird things could happen away from the surface. */ + /* Weird things can happen anyway with "clip to nearest", since this is not */ /* guaranteed to be a smooth function, depending on the gamut surface */ /* geometry, without taking some precaution such as clipping to a */ /* convex hull "wrapper" to create a clip vector, which we're not */ /* current doing. */ DBR(("Clip blend between device:\n")) - DBR(("Lab: %f %f %f and\n",pp[0].p[0], pp[0].p[1], pp[0].p[2])) - DBR(("Jab: %f %f %f\n",cpp.p[0], cpp.p[1], cpp.p[2])) + DBR(("Lab: %s & ",icmPdv(p->clutTable->di, pp[0].p))) + DBR(("Jab: %s ",icmPdv(p->clutTable->di, cpp.p))) for (e = 0; e < p->clutTable->di; e++) { out[e] = (1.0 - bf) * pp[0].p[e] + bf * cpp.p[e]; } + DBR((" = %s\n",icmPdv(p->clutTable->di, out))) /* Not CAM clip case */ } else { @@ -1459,6 +1468,7 @@ double *in /* Function input values to invert (== clut output' values) */ for (i = 0; i < nsoln; i++) { double ss; + DBR(("Soln %d: %s\n",i, icmPdv(p->clutTable->di, pp[i].p))) for (ss = 0.0, e = 0; e < p->clutTable->di; e++) { double tt; tt = pp[i].p[e] - p->licent[e]; @@ -1469,6 +1479,16 @@ double *in /* Function input values to invert (== clut output' values) */ } } } +#ifndef NEVER + // ~~99 average them + for (i = 1; i < nsoln; i++) { + for (e = 0; e < p->clutTable->di; e++) + pp[0].p[e] += pp[i].p[e]; + } + for (e = 0; e < p->clutTable->di; e++) + pp[0].p[e] /= (double)nsoln; + bsoln = 0; +#endif //printf("~1 chose %d\n",bsoln); i = bsoln; } @@ -2289,8 +2309,8 @@ fprintf(stderr,"~1 Internal optimised 4D separations not yet implemented!\n"); else xicc_enum_viewcond(xicp, &p->vc, -1, NULL, 0, NULL); /* Use a default */ p->cam = new_icxcam(cam_default); - p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, p->vc.Yf, - p->vc.Fxyz, XICC_USE_HK); + p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, + p->vc.Yf, p->vc.Yg, p->vc.Gxyz, XICC_USE_HK); } else { p->cam = NULL; } @@ -2477,10 +2497,12 @@ icxLuLut_clut_camclip_func( luluto->output(luluto, out, out); luluto->out_abs(luluto, out, out); p->cam->XYZ_to_cam(p->cam, out, out); + out[0] *= CCJSCALE; } /* Initialise the additional CAM space clut rspl, used to compute */ /* reverse lookup CAM clipping results when the camclip flag is set. */ +/* We scale J by CCJSCALE, to give a more L* preserving clip direction */ /* return error code. */ static int icxLuLut_init_clut_camclip( @@ -2490,7 +2512,7 @@ icxLuLut *p) { /* Setup so clut contains transform to CAM Jab */ /* (camclip is only used in fwd or invfwd direction lookup) */ double cmin[3], cmax[3]; - cmin[0] = 0.0; cmax[0] = 100.0; /* Nominal Jab output ranges */ + cmin[0] = 0.0; cmax[0] = CCJSCALE * 100.0; /* Nominal Jab output ranges */ cmin[1] = -128.0; cmax[1] = 128.0; cmin[2] = -128.0; cmax[2] = 128.0; @@ -2835,6 +2857,7 @@ double dispLuminance, /* > 0.0 if display luminance value and is kno double wpscale, /* > 0.0 if white point is to be scaled */ double smooth, /* RSPL smoothing factor, -ve if raw */ double avgdev, /* reading Average Deviation as a prop. of the input range */ +double demph, /* dark emphasis factor for cLUT grid res. */ icxViewCond *vc, /* Viewing Condition (NULL if not using CAM) */ icxInk *ink, /* inking details (NULL for default) */ int quality /* Quality metric, 0..3 */ @@ -2906,15 +2929,18 @@ int quality /* Quality metric, 0..3 */ /* (This is for rspl scattered data fitting smoothness adjustment) */ /* (This could do with more tuning) */ - /* For some unknown reason XYZ seems masively under-smoothed, so bump it up */ + /* XYZ display models are under-smoothed, because the mapping is typically */ + /* very "straight", and the lack of tension reduces any noise reduction effect. */ + /* !!! This probably means that we should switch to 3rd order smoothness criteria !! */ + /* We apply an arbitrary correction here */ if (p->pcs == icSigXYZData) { - oavgdev[0] = 1.0 * 0.60 * avgdev; - oavgdev[1] = 1.0 * 1.00 * avgdev; - oavgdev[2] = 1.0 * 0.60 * avgdev; + oavgdev[0] = XYZ_EXTRA_SMOOTH * 0.70 * avgdev; + oavgdev[1] = XYZ_EXTRA_SMOOTH * 1.00 * avgdev; + oavgdev[2] = XYZ_EXTRA_SMOOTH * 0.70 * avgdev; } else if (p->pcs == icSigLabData) { oavgdev[0] = 1.00 * avgdev; - oavgdev[1] = 0.60 * avgdev; - oavgdev[2] = 0.60 * avgdev; + oavgdev[1] = 0.70 * avgdev; + oavgdev[2] = 0.70 * avgdev; } else { /* Hmmm */ for (f = 0; f < p->outputChan; f++) oavgdev[f] = avgdev; @@ -3348,7 +3374,7 @@ int quality /* Quality metric, 0..3 */ if (xf->fit(xf, xfflags, p->inputChan, p->outputChan, rsplflags, wp, dwhite, wpscale, dgwhite, ipoints, nodp, skm, in_min, in_max, gres, out_min, out_max, - smooth, oavgdev, iord, sord, oord, shp_smooth, out_smooth, tcomb, + smooth, oavgdev, demph, iord, sord, oord, shp_smooth, out_smooth, tcomb, (void *)p, xfit_to_de2, xfit_to_dde2) != 0) { p->pp->errc = 2; sprintf(p->pp->err,"xfit fitting failed"); @@ -3821,7 +3847,8 @@ int quality /* Quality metric, 0..3 */ NULL, NULL, /* Use default Maximum range of Dev' values */ set_clut, /* Dev' -> PCS' transfer function */ NULL, NULL, /* Use default Maximum range of PCS' values */ - set_output /* Linear output transform PCS'->PCS */ + set_output, /* Linear output transform PCS'->PCS */ + NULL, NULL /* No APXLS */ ) != 0) error("Setting 16 bit %s->%s Lut failed: %d, %s", icm2str(icmColorSpaceSignature, h->colorSpace), @@ -3843,8 +3870,8 @@ int quality /* Quality metric, 0..3 */ else xicc_enum_viewcond(xicp, &p->vc, -1, NULL, 0, NULL); /* Use a default */ p->cam = new_icxcam(cam_default); - p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, p->vc.Yf, - p->vc.Fxyz, XICC_USE_HK); + p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, + p->vc.Yf, p->vc.Yg, p->vc.Gxyz, XICC_USE_HK); if (flags & ICX_VERBOSE) printf("Done A to B table creation\n"); |