summaryrefslogtreecommitdiff
path: root/gamut/nearsmth.c
diff options
context:
space:
mode:
Diffstat (limited to 'gamut/nearsmth.c')
-rw-r--r--gamut/nearsmth.c287
1 files changed, 185 insertions, 102 deletions
diff --git a/gamut/nearsmth.c b/gamut/nearsmth.c
index a13442d..c0bd2be 100644
--- a/gamut/nearsmth.c
+++ b/gamut/nearsmth.c
@@ -66,7 +66,7 @@
#undef PLOT_EVECTS /* [Und] Create VRML of error correction vectors */
#undef VERB /* [Und] [0] If <= 1, print progress headings */
/* if > 1, print information about everything */
-#undef SHOW_NEIGB_WEIGHTS /* [Und] Show the weighting for each point of neighbours */
+#undef SHOW_NEIGB_WEIGHTS /* [Und] Show the weighting for each point of neighbours in turn */
#undef DIAG_POINTS /* [Und] Short circuite mapping and show vectors of various */
/* intermediate points (see #ifdef DIAG_POINTS) */
@@ -81,8 +81,8 @@
#define VECSMOOTHING /* [Def] Enable vector smoothing */
#define VECADJPASSES 3 /* [3] Adjust vectors after smoothing to be on dest gamut */
#define RSPLPASSES 4 /* [4] Number of rspl adjustment passes */
-#define RSPLSCALE 1.8 /* [1.8] Offset within gamut for rspl smoothingto aim for */
-#define SHRINK 5.0 /* Shrunk destination evect surface factor */
+#define RSPLSCALE 1.8 /* [1.8] Offset within gamut for rspl smoothing to aim for */
+#define SHRINK 5.0 /* [5.0] Shrunk destination evect surface factor */
#define CYLIN_SUBVEC /* [Def] Make sub-vectors always cylindrical direction */
#define SUBVEC_SMOOTHING /* [Def] Smooth the sub-vectors */
@@ -96,6 +96,8 @@
#undef LINEAR_HUE_SUM /* Make delta^2 = (sqrt(l^2 + c^2) + h)^2 */
+#undef DEBUG_POWELL_FAILS /* [Und] On a powell fail, re-run it with debug on */
+
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(VERB)
# define VA(xxxx) printf xxxx
@@ -313,14 +315,14 @@ struct _smthopt {
gamut *sgam; /* Source colorspace gamut */
/* Cusp alignment mapping */
- /* 0 = src, 1 = dst, then cusp then value(s) */
- double cusps[2][9][3]; /* raw cusp values - red .. magenta, white [6], black [7] & grey [8] */
+ /* [2] 0 = src, 1 = dst, then cusp then value(s) */
+ double cusps[2][9][3]; /* raw cusp values - R Y G C B M, white [6], black [7] & grey [8] */
double rot[2][3][4]; /* Rotation to align to black/white center */
double irot[2][3][4]; /* Inverse rotation */
double cusp_lab[2][9][3]; /* Cusp + B&W + grey rotated Lab value */
double cusp_lch[2][6][3]; /* Cusp LCH value */
double cusp_pe[2][6][4]; /* L direction plane equations per segment */
- double cusp_bc[2][6][2][3][3]; /* light/dark to/from 3x3 baricentic transform matrix */
+ double cusp_bc[2][6][2][3][3]; /* [light/dark][Hex][to/from] 3x3 baricentic transform matrix */
/* Inversion support */
double tv[3];
@@ -382,9 +384,9 @@ double *_dv
if (p->swap) {
/* This is actually a point on the real source gamut, so */
- /* convert to cusp mapped rotated, elevated source gamut value */
+ /* convert to cusp mapped rotated source gamut value */
comp_ce(s, ddv, ddv, &p->wt);
-// printf("~1 after rot & elevate got %f %f %f\n",ddv[0],ddv[1],ddv[2]);
+//printf("~1 after cusp rot got %f %f %f\n",ddv[0],ddv[1],ddv[2]);
}
#ifdef NEVER
@@ -840,10 +842,11 @@ double out[3],
double in[3],
gammapweights *wt /* If NULL, assume 100% */
) {
- double cw_l = 1.0;
+ double cw_l = 1.0; /* Cusp adapation weighting */
double cw_c = 1.0;
double cw_h = 1.0;
- double ccx = 1.0;
+ double ctw = 1.0; /* Twist power */
+ double ccx = 1.0; /* Expansion ratio */
out[0] = in[0];
out[1] = in[1];
@@ -853,24 +856,27 @@ gammapweights *wt /* If NULL, assume 100% */
cw_l = wt->c.w.l;
cw_c = wt->c.w.c;
cw_h = wt->c.w.h;
+ ctw = wt->c.tw;
ccx = wt->c.cx;
}
/* Compute source changes due to any cusp mapping */
- if (s->docusp && (cw_l > 0.0 || cw_c > 0.0 || cw_h > 0.0)) {
+ if (s->docusp && (cw_l > 0.0 || cw_c > 0.0 || cw_h > 0.0 || ccx > 0.0)) {
double lab[3], lch[3]; /* Normalized source values */
- double bb[3]; /* Baricentric coords */
+ double bb[3]; /* Baricentric coords: cusp0, cusp1, w/b weight. */
double olch[3]; /* Destination transformed LCh source value */
double mlab[3], mlch[3]; /* Fully mapped value */
int c0, c1; /* Cusp indexes */
int ld; /* light/dark index */
+ double tww, tpw; /* Base twist weighting, twist power weightign */
-//printf("\n~1 in = %f %f %f, ccx = %f\n",in[0],in[1],in[2],ccx);
+//printf("\n~1 in = %f %f %f, cw_l %f, cw_c %f cw_h %f ctw %f ccx %f\n",in[0],in[1],in[2], cw_l, cw_c, cw_h, ctw, ccx);
- /* Compute src cusp normalized LCh */
+ /* Compute src white/black aligned input Lab & LCh */
icmMul3By3x4(lab, s->rot[0], in);
icmLab2LCh(lch, lab);
-//printf("~1 lab = %f %f %f, lch = %f %f %f\n",lab[0],lab[1],lab[2],lch[0],lch[1],lch[2]);
+//printf("~1 aligned lab = %f %f %f\n",lab[0],lab[1],lab[2]);
+//printf("~1 aligned lch = %f %f %f\n",lch[0],lch[1],lch[2]);
/* Locate the source cusps that this point lies between */
for (c0 = 0; c0 < 6; c0++) {
@@ -900,34 +906,59 @@ gammapweights *wt /* If NULL, assume 100% */
/* Compute baricentric for input point in simplex */
icmSub3(bb, lab, s->cusp_lab[0][8]);
icmMulBy3x3(bb, s->cusp_bc[0][c0][ld], bb);
+//printf("~1 bb %f %f %f sum %f\n",bb[0],bb[1],bb[2], bb[0] + bb[1]);
+
+ /* bb[0] + bb[1] is close to C value */
+ tww = fabs(bb[0] + bb[1]);
+ if (tww > 1.0)
+ tww = 1.0;
+
+ ccx = 1.0 + ((ccx - 1.0) * tww); /* Scale expansion by C anyway */
-//printf("~1 bb %f %f %f\n",bb[0],bb[1],bb[2]);
+ /* Twist power weighting */
+ if (ctw <= 0.0)
+ tpw = 1.0; /* Linear cusp alignmen mapping */
+ else
+ tpw = pow(tww, ctw); /* Less mapping near neutral, full at cusps */
+
+//printf("~1 ccx %f, tww %f, tpw %f\n", ccx, tww, tpw);
+
+ /* Scale size of mapping down near neutral with higher twist power */
+ cw_l *= tpw;
+ cw_h *= tpw;
+ cw_c *= tpw;
/* Then compute value for output from baricentric */
icmMulBy3x3(mlab, s->cusp_bc[1][c0][ld], bb);
icmAdd3(mlab, mlab, s->cusp_lab[1][8]);
icmLab2LCh(mlch, mlab);
-//printf("~1 fully cusp mapped point %f %f %f\n", mlab[0], mlab[1], mlab[2]);
+//printf("~1 full mapped point lch %f %f %f\n", mlch[0], mlch[1], mlch[2]);
- /* Compute the unchanged source in dest space */
+ /* Compute the unchanged source in dest black/white aligned space */
icmMul3By3x4(olch, s->rot[1], in);
icmLab2LCh(olch, olch);
+//printf("~1 un mappedpoint lch %f %f %f\n", olch[0], olch[1], olch[2]);
+
/* Then compute weighted output */
mlch[0] = cw_l * mlch[0] + (1.0 - cw_l) * olch[0];
mlch[1] = cw_c * mlch[1] + (1.0 - cw_c) * olch[1];
- mlch[1] *= ccx; /* Chroma expansion */
-
- if (lch[2] > mlch[2] && (lch[2] - mlch[2]) > 180.0)
- mlch[2] += 360.0;
- else if (mlch[2] > lch[2] && (mlch[2] - lch[2]) > 180.0)
- lch[2] += 360.0;
- mlch[2] = cw_c * mlch[2] + (1.0 - cw_c) * lch[2];
+ if (fabs(olch[2] - mlch[2]) > 180.0) { /* Put them on the same side */
+ if (olch[2] < mlch[2])
+ olch[2] += 360.0;
+ else
+ mlch[2] += 360.0;
+ }
+ mlch[2] = cw_c * mlch[2] + (1.0 - cw_c) * olch[2];
if (mlch[2] >= 360.0)
mlch[2] -= 360.0;
-//printf("~1 weighted cusp mapped point %f %f %f\n", mlch[0], mlch[1], mlch[2]);
+ mlch[1] *= ccx; /* Add chroma expansion */
+
+//printf("~1 weighted cusp mapped lch %f %f %f\n", mlch[0], mlch[1], mlch[2]);
+
+ /* Align to destination white/black axis */
icmLCh2Lab(mlch, mlch);
icmMul3By3x4(out, s->irot[1], mlch);
//printf("~1 returning %f %f %f\n", out[0], out[1], out[2]);
@@ -970,7 +1001,7 @@ double in[3] /* Non-cusp mapped source value */
return ll;
}
-/* Return a value suitable for blending between the wl, gl and bl L dominance values */
+/* Return a value suitable for blending between the wl, gl and bl L dominance values. */
/* The value is a linear blend value, 0.0 at cusp local grey, 1.0 at white L value */
/* and -1.0 at black L value. */
static double comp_lvc(
@@ -1114,6 +1145,7 @@ gammapweights *src
NSCOPY(c.w.l);
NSCOPY(c.w.c);
NSCOPY(c.w.h);
+ NSCOPY(c.tw);
NSCOPY(c.cx);
NSCOPY(l.o);
@@ -1154,6 +1186,7 @@ gammapweights *src2, double wgt2
NSBLEND(c.w.l);
NSBLEND(c.w.c);
NSBLEND(c.w.h);
+ NSBLEND(c.tw);
NSBLEND(c.cx);
NSBLEND(l.o);
@@ -1183,7 +1216,7 @@ gammapweights *src2, double wgt2
}
/* Expand the compact form of weights into the explicit form. */
-/* The explicit form is light and dark of red, yellow, green, cyan, blue, magenta & neutral*/
+/* The explicit form is light and dark of red, yellow, green, cyan, blue, magenta & neutral */
/* Return nz on error */
int expand_weights(gammapweights out[14], gammapweights *in) {
int i, j;
@@ -1299,7 +1332,7 @@ int expand_weights(gammapweights out[14], gammapweights *in) {
return 0;
}
-/* Tweak weights acording to extra cmy cusp flags or rel override */
+/* Tweak weights acording to extra cmy cusp mapping flags or rel override */
void tweak_weights(gammapweights out[14], int dst_cmymap, int rel_oride) {
int i;
@@ -1311,6 +1344,7 @@ void tweak_weights(gammapweights out[14], int dst_cmymap, int rel_oride) {
out[i].c.w.l = 1.0; /* 100% mapping */
out[i].c.w.c = 1.0;
out[i].c.w.h = 1.0;
+ out[i].c.tw = 1.0; /* Moderate twist */
out[i].c.cx = 1.0; /* No expansion */
}
@@ -1364,7 +1398,7 @@ static void comp_iweight(iweight *iw, double o, double h, double l) {
}
/* Given a point location, return the interpolated weighting values at that point. */
-/* (Typically non-cusp mapped source location assumed, and source gamut cusps used) */
+/* (Typically non-cusp mapped source location assumed, and source gamut cusps used.) */
/* (Assume init_ce() has been called to setip smthopt!) */
void interp_xweights(gamut *gam, gammapweights *out, double pos[3],
gammapweights in[14], smthopt *s, int cvec) {
@@ -1787,13 +1821,18 @@ datao map_oh
if (si_gam != sc_gam) {
if ((sci_gam = new_gamut(0.0, 0, 0)) == NULL) {
fprintf(stderr,"gamut map: new_gamut failed\n");
+ free_nearsmth(smp, nmpts);
*npp = 0;
return NULL;
}
sci_gam->intersect(sci_gam, sc_gam, si_gam);
#ifdef SAVE_VRMLS
- printf("###### gamut/nearsmth.c: writing diagnostic sci_gam.wrl and di_gam.wrl\n");
- sci_gam->write_vrml(sci_gam, "sci_gam.wrl", 1, 0);
+ {
+ char sci_gam_name[40] = "sci_gam";
+ strcat(sci_gam_name, vrml_ext());
+ printf("###### gamut/nearsmth.c: writing diagnostic sci_gam%s and di_gam%s\n",vrml_ext(),vrml_ext());
+ sci_gam->write_vrml(sci_gam, sci_gam_name, 1, 0);
+ }
#endif
}
@@ -1803,6 +1842,7 @@ datao map_oh
fprintf(stderr,"gamut map: new_gamut failed\n");
if (si_gam != sc_gam)
sci_gam->del(sci_gam);
+ free_nearsmth(smp, nmpts);
*npp = 0;
return NULL;
}
@@ -1813,6 +1853,7 @@ datao map_oh
di_gam->del(di_gam);
if (si_gam != sc_gam)
sci_gam->del(sci_gam);
+ free_nearsmth(smp, nmpts);
*npp = 0;
return NULL;
}
@@ -1828,7 +1869,11 @@ datao map_oh
}
#ifdef SAVE_VRMLS
- di_gam->write_vrml(di_gam, "di_gam.wrl", 1, 0);
+ {
+ char di_gam_name[30] = "di_gam";
+ strcat(di_gam_name, vrml_ext());
+ di_gam->write_vrml(di_gam, di_gam_name, 1, 0);
+ }
#endif
/* Create a list of the mapping guide points, setup for a null mapping */
@@ -1868,6 +1913,7 @@ datao map_oh
smp[i].dv[2] = smp[i].sv[2] = smp[i]._sv[2] = imv[2];
smp[i].sgam = sci_gam;
smp[i].dgam = sci_gam;
+ smp[i].mapres = mapres;
VB(("In Src %d = %f %f %f\n",i,smp[i].sv[0],smp[i].sv[1],smp[i].sv[2]));
@@ -1952,7 +1998,6 @@ datao map_oh
imv[2] = smp[i]._sv[2];
/* Compute the cusp rotated version of the cspace/image points */
- /* Note that we're not elevating yet! */
comp_ce(&opts, rimv, imv, &smp[i].wt);
VB(("%f de, ix %d: cusp mapped %f %f %f -> %f %f %f\n", icmNorm33(rimv,imv), i, imv[0], imv[1], imv[2], rimv[0], rimv[1], rimv[2]));
rimr = icmNorm33(rimv, sci_gam->cent);
@@ -1976,7 +2021,7 @@ datao map_oh
smp[i].dr = icmNorm33(smp[i].dv, smp[i].dgam->cent);
/* Re-lookup radialy equivalent point on destination gamut, */
- /* to match rotated/elevated source */
+ /* to match rotated source */
smp[i].drr = smp[i].dgam->radial(smp[i].dgam, smp[i].drv, smp[i].sv);
/* A default average neighbour value */
@@ -2086,7 +2131,7 @@ datao map_oh
for (i = 0; i < nmpts; i++) {
double x, y, z, tv[3];
- /* compute rotated location */
+ /* compute tangent alignment rotated location */
icmNormalize33(tt, smp[i].sv, smp[ix].sgam->cent, 1.0);
icmMul3By3x4(tv, mm, tt);
icmMulBy2x2(&tv[1], m2, &tv[1]);
@@ -2203,8 +2248,8 @@ datao map_oh
for (i = 0; i < nmpts; i++) {
double maxw;
- if ((wrl = new_vrml("weights.wrl", 1)) == NULL)
- error("New vrml failed");
+ if ((wrl = new_vrml("weights", 1, vrml_lab)) == NULL)
+ error("New %s failed for '%s%s'",vrml_format(),"weights",vrml_ext());
maxw = 0.0;
for (j = 0; j < smp[i].nnd; j++) {
@@ -2219,7 +2264,7 @@ datao map_oh
wrl->make_lines(wrl, 0, 2);
wrl->del(wrl);
- printf("Waiting for input after writing 'weights.wrl' for point %d:\n",i);
+ printf("Waiting for input after writing 'weights%s' for point %d:\n",vrml_ext(),i);
getchar();
}
}
@@ -2296,8 +2341,8 @@ datao map_oh
nv[1] = iv[1] + d_rand(-20.0, 20.0);
}
if (brv == 1e38) { /* We failed to get a result */
- VB(("multiple powells failed to get a result\n"));
-#ifdef NEVER
+ fprintf(stderr, "multiple powells failed to get a result (1)\n");
+#ifdef DEBUG_POWELL_FAILS
/* Optimise the point with debug on */
opts.debug = 1;
icmMul3By3x4(iv, smp[i].m2d, smp[i].dv);
@@ -2305,12 +2350,12 @@ datao map_oh
nv[1] = iv[1] = iv[2];
powell(NULL, 2, nv, s, 0.01, 1000, optfunc1, (void *)(&opts), NULL, NULL);
#endif
- free_nearsmth(smp, nmpts);
- *npp = 0;
if (si_gam != sc_gam)
sci_gam->del(sci_gam);
if (di_gam != sci_gam && di_gam != sci_gam)
di_gam->del(di_gam);
+ free_nearsmth(smp, nmpts);
+ *npp = 0;
return NULL;
}
@@ -2401,8 +2446,8 @@ datao map_oh
nv[1] = iv[1] + d_rand(-20.0, 20.0);
}
if (brv == 1e38) { /* We failed to get a result */
- VB(("multiple powells failed to get a result\n"));
-#ifdef NEVER
+ fprintf(stderr, "multiple powells failed to get a result (2)\n");
+#ifdef DEBUG_POWELL_FAILS
/* Optimise the point with debug on */
opts.debug = 1;
icmMul3By3x4(iv, smp[i].m2d, smp[i].dv);
@@ -2410,12 +2455,12 @@ datao map_oh
nv[1] = iv[1] = iv[2];
powell(NULL, 2, nv, s, 0.01, 1000, optfunc2, (void *)(&opts), NULL, NULL);
#endif
- free_nearsmth(smp, nmpts);
- *npp = 0;
if (si_gam != sc_gam)
sci_gam->del(sci_gam);
if (di_gam != sci_gam && di_gam != sci_gam)
di_gam->del(di_gam);
+ free_nearsmth(smp, nmpts);
+ *npp = 0;
return NULL;
}
@@ -2481,12 +2526,13 @@ datao map_oh
if ((shgam = new_gamut(di_gam->getsres(di_gam), di_gam->getisjab(di_gam),
di_gam->getisrast(di_gam))) == NULL) {
- free_nearsmth(smp, nmpts);
- *npp = 0;
+ fprintf(stderr, "new_gamut failed\n");
if (si_gam != sc_gam)
sci_gam->del(sci_gam);
if (di_gam != sci_gam && di_gam != sci_gam)
di_gam->del(di_gam);
+ free_nearsmth(smp, nmpts);
+ *npp = 0;
return NULL;
}
@@ -2521,13 +2567,13 @@ datao map_oh
if ((gpnts = (cow *)malloc(nmpts * sizeof(cow))) == NULL) {
fprintf(stderr,"gamut map: Malloc of near smooth points failed\n");
- free_nearsmth(smp, nmpts);
- *npp = 0;
shgam->del(shgam);
if (si_gam != sc_gam)
sci_gam->del(sci_gam);
if (di_gam != sci_gam && di_gam != sci_gam)
di_gam->del(di_gam);
+ free_nearsmth(smp, nmpts);
+ *npp = 0;
return NULL;
}
@@ -2569,14 +2615,22 @@ datao map_oh
nv[1] = iv[1] + d_rand(-20.0, 20.0);
}
if (brv == 1e38) { /* We failed to get a result */
- VB(("multiple powells failed to get a result\n"));
+ fprintf(stderr, "multiple powells failed to get a result (3)\n");
+#ifdef DEBUG_POWELL_FAILS
+ /* Optimise the point with debug on */
+ opts.debug = 1;
+ icmMul3By3x4(iv, smp[i].m2d, smp[i].dv);
+ nv[0] = iv[0] = iv[1];
+ nv[1] = iv[1] = iv[2];
+ powell(NULL, 2, nv, s, 0.01, 1000, optfunc1a, (void *)(&opts), NULL, NULL);
+#endif
shgam->del(shgam); /* Done with this */
- free_nearsmth(smp, nmpts);
- *npp = 0;
if (si_gam != sc_gam)
sci_gam->del(sci_gam);
if (di_gam != sci_gam && di_gam != sci_gam)
di_gam->del(di_gam);
+ free_nearsmth(smp, nmpts);
+ *npp = 0;
return NULL;
}
@@ -2628,12 +2682,14 @@ datao map_oh
double green[3] = { 0.0, 1.0, 0.0 };
double tmp[3];
co cp;
+
#ifdef PLOT_AXES
doaxes = 1;
#endif
- printf("###### gamut/nearsmth.c: writing diagnostic evects.wrl\n");
- wrl = new_vrml("evects.wrl", doaxes);
+ printf("###### gamut/nearsmth.c: writing diagnostic evects%s\n",vrml_ext());
+ if ((wrl = new_vrml("evects", doaxes, vrml_lab)) == NULL)
+ error("new_vrml failed for '%s%s'","evects",vrml_ext());
wrl->make_gamut_surface_2(wrl, di_gam, 0.6, 0, cc);
cc[0] = -1.0;
wrl->make_gamut_surface(wrl, shgam, 0.2, cc);
@@ -2890,14 +2946,14 @@ datao map_oh
if ((gpnts = (cow *)malloc(nmpts * sizeof(cow))) == NULL) {
fprintf(stderr,"gamut map: Malloc of near smooth points failed\n");
- free_nearsmth(smp, nmpts);
- *npp = 0;
if (evectmap != NULL)
evectmap->del(evectmap);
if (si_gam != sc_gam)
sci_gam->del(sci_gam);
if (di_gam != sci_gam && di_gam != sci_gam)
di_gam->del(di_gam);
+ free_nearsmth(smp, nmpts);
+ *npp = 0;
return NULL;
}
@@ -3131,7 +3187,7 @@ datao map_oh
VB(("Final guide points:\n"));
- /* Restore the actual non elevated and cust rotated source point */
+ /* Restore the actual non cusp rotated source point */
for (i = 0; i < nmpts; i++) {
VB(("Src %d = %f %f %f\n",i,smp[i].sv[0],smp[i].sv[1],smp[i].sv[2]));
@@ -3152,7 +3208,10 @@ datao map_oh
/* Create sub-surface points. */
for (i = 0; i < nmpts; i++) {
- /* Create a sub-surface mapping point too. */
+ /* Create sub-surface mapping points too. We control the degree */
+ /* of knee with a extrapolated destination point dv2, where */
+ /* the degree of extrapolation is inversly related to the sharpness of the knee. */
+ /* A third point maps 1:1 with a weight that is related the sharpness. */
/* Note that not every mapping point has a sub-surface point, */
/* and that the gflag and vflag will be nz if it does. */
/* We're assuming here that the dv is close to being on the */
@@ -3160,7 +3219,7 @@ datao map_oh
/* close to 1.0 at the intended destination gamut. */
{
double mv[3], ml, nv[3]; /* Mapping vector & length, noralized mv */
- double minv[3], maxv[3];
+ double minv[3], maxv[3]; /* (Not used) */
double mint, maxt;
gtri *mintri, *maxtri;
@@ -3174,7 +3233,9 @@ datao map_oh
//if (PFCOND) printf("~1 mapping %d = %f %f %f -> %f %f %f\n", i, smp[i].sv[0],smp[i].sv[1],smp[i].sv[2],smp[i].dv[0],smp[i].dv[1],smp[i].dv[2]);
//if (PFCOND) printf("~1 vector %f %f %f, len %f\n", mv[0], mv[1], mv[2],ml);
+
/* Compute actual depth of ray into destination gamut */
+ /* to determine if this is expansion or contraction. */
if (di_gam->vector_isect(di_gam, smp[i].sv, smp[i].dv,
minv, maxv, &mint, &maxt, &mintri, &maxtri) != 0) {
double wp[3], bp[3]; /* Gamut white and black points */
@@ -3190,22 +3251,41 @@ datao map_oh
/* a sanity check on the available depth. */
if (d_gam->getwb(d_gam, NULL, NULL, NULL, wp, dst_kbp ? NULL : bp, dst_kbp ? bp : NULL) == 0) {
if (icmLineLineClosest(napoint, NULL, &p1, NULL, bp, wp,
- smp[i].sv,smp[i].dv) == 0) {
- /* Clip it */
- if (p1 < 0.0)
- icmCpy3(napoint, bp);
- else if (p1 > 1.0)
- icmCpy3(napoint, wp);
+ smp[i].sv, smp[i].dv) == 0) {
+ double nalev[3];
+ icmCpy3(nalev, napoint);
//if (PFCOND) printf("~1 neutral axis point = %f %f %f\n", napoint[0], napoint[1], napoint[2]);
/* Compute a normalized available depth from distance */
/* to closest to neautral axis point */
if ((mint > 1e-8 && maxt > -1e-8) /* G. & V. Compression */
|| ((mint < -1e-8 && maxt > -1e-8) /* G. Exp & V. comp. */
- && (fabs(mint) < (fabs(maxt) - 1e-8))))
+ && (fabs(mint) < (fabs(maxt) - 1e-8)))) {
+ /* Compression */
+
+ /* Moderate the neutral axis point to be half way */
+ /* between sv->dv direction, and horizontal. */
+ nalev[0] = smp[i].dv[0];
+ icmBlend3(napoint, napoint, nalev, 0.5);
+ /* Clip it to be between black and white point */
+ if (napoint[0] < bp[0])
+ icmCpy3(napoint, bp);
+ else if (napoint[0] > wp[0])
+ icmCpy3(napoint, wp);
adepth2 = icmNorm33(napoint, smp[i].dv);
- else /* Expansion */
+ } else {
+ /* Expansion */
+ /* Moderate the neutral axis point to be half way */
+ /* between sv->dv direction, and horizontal. */
+ nalev[0] = smp[i].sv[0];
+ icmBlend3(napoint, napoint, nalev, 0.5);
+ /* Clip it to be between black and white point */
+ if (napoint[0] < bp[0])
+ icmCpy3(napoint, bp);
+ else if (napoint[0] > wp[0])
+ icmCpy3(napoint, wp);
adepth2 = icmNorm33(napoint, smp[i].sv);
+ }
}
#ifdef VERB
else {
@@ -3232,10 +3312,11 @@ datao map_oh
if (fabs(mint - 1.0) < fabs(maxt) - 1.0
&& smp[i].dgam->radial(smp[i].dgam, NULL, smp[i].dv)
< smp[i].sgam->radial(smp[i].sgam, NULL, smp[i].dv)) {
+ double sgamcknf = gamcknf * 0.6; /* [0.7] Scale to limit overshoot */
//if (PFCOND) printf("~1 point is gamut comp & vect comp.\n");
//if (PFCOND) printf("~1 point is gamut comp & vect comp. mint %f maxt %f\n",mint,maxt);
- adepth1 = ml * 0.5 * (maxt + mint - 2.0);
+ adepth1 = ml * 0.5 * (maxt + mint - 2.0); /* Average depth */
#ifdef CYLIN_SUBVEC
adepth = adepth2; /* Always cylindrical depth */
#else
@@ -3243,36 +3324,45 @@ datao map_oh
#endif
if (adepth1 < (0.5 * adepth2))
continue;
+
//if (PFCOND) printf("~1 dir adepth %f, radial adapeth %f\n",adepth1,adepth2);
- adepth *= 0.9; /* Can't use 100% */
+ adepth *= 0.9; /* Can't use 100% */
smp[i].gflag = 1; /* Gamut compression and */
smp[i].vflag = 1; /* vector compression */
/* Compute available depth and knee factor adjusted sub-vector */
icmCpy3(smp[i].sv2, smp[i].dv); /* Sub source is guide dest */
- ml *= (1.0 - gamcknf); /* Scale by knee */
- adepth *= (1.0 - gamcknf);
+ ml *= (1.0 - sgamcknf); /* Scale by knee */
+ adepth *= (1.0 - sgamcknf);
sml = ml < adepth ? ml : adepth; /* Smaller of two */
//if (PFCOND) printf("~1 adjusted subvec len %f\n",sml);
icmNormalize3(mv2, mv, sml); /* Full sub-surf disp. == no knee */
icmAdd3(mv2, smp[i].sv2, mv2); /* Knee adjusted destination */
//if (PFCOND) printf("~1 before blend sv2 %f %f %f, dv2 %f %f %f\n", smp[i].sv2[0], smp[i].sv2[1], smp[i].sv2[2], mv2[0], mv2[1], mv2[2]);
- /* Blend towards n.axis as length of sub vector approaches */
- /* distance to neutral axis. */
+ /* Compute point at sml depth from sv2 towards napoint */
icmSub3(natarg, napoint, smp[i].sv2);
icmNormalize3(natarg, natarg, sml); /* Sub vector towards n.axis */
icmAdd3(natarg, natarg, smp[i].sv2); /* n.axis target */
#ifdef CYLIN_SUBVEC
icmCpy3(mv2, natarg); /* cylindrical direction vector */
#else
+ /* Blend towards n.axis as length of sub vector approaches */
+ /* distance to neutral axis. */
icmBlend3(mv2, mv2, natarg, sml/adepth2);
#endif /* CYLIN_SUBVEC */
//if (PFCOND) printf("~1 after blend sv2 %f %f %f, dv2 %f %f %f\n", smp[i].sv2[0], smp[i].sv2[1], smp[i].sv2[2], mv2[0], mv2[1], mv2[2]);
icmCpy3(smp[i].dv2, mv2); /* Destination */
icmCpy3(smp[i].temp, smp[i].dv2); /* Save a copy to temp */
- smp[i].w2 = 0.8;
+ smp[i].w2 = 0.7; /* De-weight due to density */
+
+ icmBlend3(mv2, mv2, napoint, 0.6); /* Half way to na */
+ icmCpy3(smp[i].sd3, mv2);
+
+ smp[i].w3 = 0.4 * gamcknf; /* [0.3] Weight with knee factor */
+ /* and to control overshoot */
+
} else {
//if (PFCOND) printf("~1 point is gamut exp & vect exp. mint %f maxt %f\n",mint,maxt);
smp[i].gflag = 2; /* Gamut expansion and */
@@ -3323,6 +3413,10 @@ datao map_oh
icmCpy3(smp[i].temp, smp[i].dv2); /* Save a copy to temp */
smp[i].w2 = 0.8;
+ icmBlend3(mv2, mv2, napoint, 0.5); /* Half way to na */
+ icmCpy3(smp[i].sd3, mv2);
+ smp[i].w3 = 0.3 * gamcknf; /* Weight with knee fact */
+
/* Conflicted case */
} else {
/* Nonsense vector */
@@ -3421,9 +3515,11 @@ void free_nearsmth(nearsmth *smp, int nmpts) {
/* =================================================================== */
#if defined(SAVE_VRMLS) && defined(PLOT_MAPPING_INFLUENCE)
+
/* Create a plot indicating how the source mapping has been guided by the */
-/* various weighting forces */
+/* various weighting forces. */
static void create_influence_plot(nearsmth *smp, int nmpts) {
+ int i, j, k;
gamut *gam;
int src = 0; /* 1 = src, 0 = dst gamuts */
vrml *wrl = NULL;
@@ -3440,20 +3536,14 @@ static void create_influence_plot(nearsmth *smp, int nmpts) {
int ix;
if (src)
- gam = sci_gam;
+ gam = smp->sgam;
else
- gam = di_gam;
+ gam = smp->dgam;
/* Setup the scattered data points */
if ((fpnts = (co *)malloc((nmpts) * sizeof(co))) == NULL) {
fprintf(stderr,"gamut map: Malloc of diagnostic mapping setup points failed\n");
- if (si_gam != sc_gam)
- sci_gam->del(sci_gam);
- if (di_gam != sci_gam && di_gam != sci_gam)
- di_gam->del(di_gam);
- free_nearsmth(smp, nmpts);
- *npp = 0;
- return NULL;
+ return;
}
/* Compute error values and diagnostic color */
@@ -3465,7 +3555,7 @@ static void create_influence_plot(nearsmth *smp, int nmpts) {
/* Source value location */
if (src) {
for (j = 0; j < 3; j++)
- fpnts[i].p[j] = smp[i]._sv[j]; /* Non rotated and elevated */
+ fpnts[i].p[j] = smp[i]._sv[j]; /* Non cusp rotated */
} else { /* Dest value location */
for (j = 0; j < 3; j++)
fpnts[i].p[j] = smp[i].dv[j];
@@ -3502,7 +3592,7 @@ static void create_influence_plot(nearsmth *smp, int nmpts) {
/* Create the diagnostic color rspl */
for (j = 0; j < 3; j++) { /* Set resolution for all axes */
- gres[j] = mapres;
+ gres[j] = smp->mapres;
avgdev[j] = 0.001;
}
swdiag = new_rspl(RSPL_NOFLAGS, 3, 3); /* Allocate 3D -> 3D */
@@ -3510,19 +3600,11 @@ static void create_influence_plot(nearsmth *smp, int nmpts) {
/* Now create a plot of the sci_gam with the vertexes colored acording to the */
/* diagnostic map. */
- if ((wrl = new_vrml("sci_gam_wt.wrl", 1)) == NULL) {
- fprintf(stderr,"gamut map: new_vrml failed\n");
- if (fpnts != NULL)
- free(fpnts);
- if (swdiag != NULL)
- swdiag->del(swdiag);
- if (si_gam != sc_gam)
- sci_gam->del(sci_gam);
- if (di_gam != sci_gam && di_gam != sci_gam)
- di_gam->del(di_gam);
- free_nearsmth(smp, nmpts);
- *npp = 0;
- return NULL;
+ if ((wrl = new_vrml("sci_gam_wt", 1, vrml_lab)) == NULL) {
+ fprintf(stderr,"gamut map: new_vrml failed for '%s%s'\n","sci_gam_wt",vrm_ext());
+ swdiag->del(swdiag);
+ free(fpnts);
+ return;
}
/* Plot the gamut triangle vertexes */
@@ -3532,6 +3614,7 @@ static void create_influence_plot(nearsmth *smp, int nmpts) {
ix = gam->getvert(gam, NULL, pp.p, ix);
swdiag->interp(swdiag, &pp);
+ icmClip3(pp.v, pp.v);
wrl->add_col_vertex(wrl, 0, pp.p, pp.v);
}
gam->startnexttri(gam);
@@ -3543,7 +3626,7 @@ static void create_influence_plot(nearsmth *smp, int nmpts) {
}
wrl->make_triangles_vc(wrl, 0, 0.0);
- printf("Writing sci_gam_wt.wrl file\n");
+ printf("Writing sci_gam_wt%s file\n",vrml_ext());
wrl->del(wrl); /* Write file */
free(fpnts);
swdiag->del(swdiag);