summaryrefslogtreecommitdiff
path: root/gamut
diff options
context:
space:
mode:
Diffstat (limited to 'gamut')
-rw-r--r--gamut/Jamfile6
-rw-r--r--gamut/gammap.c325
-rw-r--r--gamut/gammap.h2
-rw-r--r--gamut/gamut.c816
-rw-r--r--gamut/gamut.h9
-rw-r--r--gamut/maptest.c7
-rw-r--r--gamut/nearsmth.c287
-rw-r--r--gamut/nearsmth.h17
-rw-r--r--gamut/smthtest.c247
-rw-r--r--gamut/viewgam.c260
10 files changed, 724 insertions, 1252 deletions
diff --git a/gamut/Jamfile b/gamut/Jamfile
index a7273f3..e97d0df 100644
--- a/gamut/Jamfile
+++ b/gamut/Jamfile
@@ -30,8 +30,8 @@ Library libgamut : gamut.c ;
# Gamut mapping library
Library libgammap : gammap.c nearsmth.c ;
-LINKLIBS = libgammap libgamut ../rspl/librspl ../icc/libicc ../cgats/libcgats ../numlib/libnum
- ../plot/libvrml ;
+LINKLIBS = libgammap libgamut ../rspl/librspl ../icc/libicc ../cgats/libcgats
+ ../plot/libplot ../numlib/libnum ../numlib/libui ../plot/libvrml ;
# Utilities
Main viewgam : viewgam.c ;
@@ -56,7 +56,7 @@ Main GenVisGam : GenVisGam.c ;
#Main tttt : tttt.c ;
LINKLIBS = libgammap libgamut ../icc/libicc ../cgats/libcgats ../xicc/libxicc
- ../rspl/librspl ../numlib/libnum ../plot/libplot ../plot/libvrml ;
+ ../rspl/librspl ../plot/libplot ../plot/libvrml ../numlib/libnum ../numlib/libui ;
# Mapping test routine
Main maptest : maptest.c ;
diff --git a/gamut/gammap.c b/gamut/gammap.c
index d463755..638a2cd 100644
--- a/gamut/gammap.c
+++ b/gamut/gammap.c
@@ -45,20 +45,23 @@
#define VERBOSE /* [Def] Print out extra interesting information when verbose is set */
#undef PLOT_DIAG_WRL /* [Und] Always plot "gammap.wrl" */
- /* What do display when user requests disgnostic .wrl */
+ /* What do display when user requests disgnostic VRML/X3D */
#define PLOT_SRC_GMT /* [Def] Plot the source surface to "gammap.wrl" as well */
#define PLOT_DST_GMT /* [Def] Plot the dest surface to "gammap.wrl" as well */
#undef PLOT_SRC_CUSPS /* [Und] Plot the source surface cusps to "gammap.wrl" as well */
#undef PLOT_DST_CUSPS /* [Und] Plot the dest surface cusps to "gammap.wrl" as well */
#undef PLOT_TRANSSRC_CUSPS /* [Und] Plot the gamut mapped source surface cusps to "gammap.wrl" */
-#undef PLOT_AXES /* [Und] Plot the axes to "gammap.wrl" as well */
+#define PLOT_AXES /* [Und] Plot the axes to "gammap.wrl" as well */
#undef SHOW_VECTOR_INDEXES /* [Und] Show the mapping vector index numbers */
-#define SHOW_MAP_VECTORS /* [Def] Show the mapping vectors */
-#undef SHOW_SUB_SURF /* [Und] Show the sub-surface mapping vector */
+#define SHOW_MAP_VECTORS /* [Def] Show the mapping vectors - yellow to red, green to red */
+ /* if no clear direction. */
+#undef SHOW_SUB_SURF /* [Und] Show the sub-surface mapping vector - grey to purple. */
+#undef SHOW_SUB_PNTS /* [Und] Show the sub-surface sv2 (red), div2 (green), sd3 (yellow) pnts */
#undef SHOW_CUSPMAP /* [Und] Show the cusp mapped vectors rather than final vectors */
-#undef SHOW_ACTUAL_VECTORS /* [Und?] Show how the source vectors actually map thought xform */
+#undef SHOW_ACTUAL_VECTORS /* [Und] Show how the source vectors actually map thought xform */
#undef SHOW_ACTUAL_VEC_DIFF /* [Und] Show how the difference between guide and actual vectors */
+ /* Other diagnostics */
#undef PLOT_LMAP /* [Und] Plot L map */
#undef PLOT_GAMUTS /* [Und] Save (part mapped) input and output gamuts as */
/* src.wrl, img.wrl, dst.wrl, gmsrc.wrl */
@@ -75,7 +78,11 @@
#undef PLOT_DIGAM /* [Und] Rather than DST_GMT - don't free it (#def in nearsmth.c too) */
-#define XRES 100 /* Res of plots */
+#define XRES 100 /* [100] Res of plots */
+
+/* The locus.ts file can contain source locus(es) that will be plotted */
+/* as cones in red, with the destination plotted in white. They can */
+/* be created from .tif files using xicc/tiffgmts utility. */
/* Optional marker points for gamut mapping diagnosotic */
struct {
@@ -85,6 +92,7 @@ struct {
double col[3]; /* RGB color */
} markers[] = {
{ 0, }, /* End marker */
+ { 1, { 37.18, 17.78, 20.28 }, { 0.545, 0.357, 0.256 } }, /* Dark Baby skin */
{ 1, { 12.062, -0.87946, 0.97008 }, { 1.0, 0.3, 0.3 } }, /* Black point */
{ 1, { 67.575411, -37.555250, -36.612862 }, { 1.0, 0.3, 0.3 } }, /* bad source in red (Red) */
{ 1, { 61.003078, -44.466554, 1.922585 }, { 0.0, 1.0, 0.3 } }, /* good source in green */
@@ -169,7 +177,7 @@ static void inv_grey_func(void *pp, double *out, double *in);
static void adjust_wb_func(void *pp, double *out, double *in);
static void adjust_sat_func(void *pp, double *out, double *in);
-#define XVRA 4.0 /* Extra mapping vertex ratio over no. tri verts from gamut */
+#define XVRA 3.0 /* [3.0] Extra mapping vertex ratio over no. tri verts from gamut */
/* The smoothed near weighting control values. */
/* These weightings setup the detailed behaviour of the */
@@ -186,16 +194,17 @@ gammapweights pweights[] = {
0.0, /* Cusp chroma alignment weighting 0 = none, 1 = full */
0.3 /* Cusp hue alignment weighting 0 = none, 1 = full */
},
+ 2.0, /* Alignment twist power, 0 = linear, 1 = curve, 2+ late curve */
1.00 /* Chroma expansion 1 = none */
},
- { /* Radial weighting */
+ { /* Radial weighting (currently broken - need to fix) */
0.0, /* Radial error overall weight, 0 + */
0.5, /* Radial hue dominance vs l+c, 0 - 1 */
0.5 /* Radial l dominance vs, c, 0 - 1 */
},
{ /* Weighting of absolute error of destination from source */
1.0, /* Absolute error overall weight */
- 0.6, /* Hue dominance vs l+c, 0 - 1 */
+ 0.8, /* Hue dominance vs l+c, 0 - 1 */
0.8, /* White l dominance vs, c, 0 - 1 */
0.5, /* Grey l dominance vs, c, 0 - 1 */
@@ -221,16 +230,16 @@ gammapweights pweights[] = {
0.0 /* Fine tuning expansion weight, 0 - 1 */
}
},
-#ifdef NEVER
{
- gmm_l_d_blue, /* Increase maintaining hue importance for blue */
+ gmm_light_yellow, /* Treat yellow differently, to get purer result. */
{
{
- -1.0, /* Cusp luminance alignment weighting 0 = none, 1 = full */
- -1.0, /* Cusp chroma alignment weighting 0 = none, 1 = full */
- 0.0 /* Cusp hue alignment weighting 0 = none, 1 = full */
+ 0.9, /* Cusp luminance alignment weighting 0 = none, 1 = full */
+ 0.8, /* Cusp chroma alignment weighting 0 = none, 1 = full */
+ 0.7 /* Cusp hue alignment weighting 0 = none, 1 = full */
},
- -1.0 /* Chroma expansion 1 = none */
+ 4.0, /* Alignment twist power, 0 = linear, 1 = curve, 2+ late curve */
+ 1.20 /* Chroma expansion 1 = none */
},
{ /* Radial weighting */
-1.0, /* Radial error overall weight, 0 + */
@@ -239,7 +248,7 @@ gammapweights pweights[] = {
},
{ /* Weighting of absolute error of destination from source */
-1.0, /* Absolute error overall weight */
- 0.8, /* Hue dominance vs l+c, 0 - 1 */
+ -1.0, /* Hue dominance vs l+c, 0 - 1 */
-1.0, /* White l dominance vs, c, 0 - 1 */
-1.0, /* Grey l dominance vs, c, 0 - 1 */
@@ -252,7 +261,7 @@ gammapweights pweights[] = {
-1.0 /* L error xover threshold in DE */
},
{ /* Relative error preservation using smoothing */
- -1.0, 25.0 /* Relative Smoothing radius L* H* */
+ 20.0, 10.0 /* Relative Smoothing radius L* H* */
},
{ /* Weighting of excessive compression error, which is */
/* the src->dst vector length over the available dst depth. */
@@ -262,19 +271,20 @@ gammapweights pweights[] = {
-1.0 /* Expansion depth weight */
},
{
- -1.0 /* Fine tuning expansion weight, 0 - 1 */
+ 0.5 /* Fine tuning expansion weight, 0 - 1 */
}
},
-#endif /* NEVER */
+#ifdef NEVER
{
- gmm_light_yellow, /* Treat yellow differently, to get purer result. */
+ gmm_l_d_blue, /* Increase maintaining hue importance for blue */
{
{
- 0.9, /* Cusp luminance alignment weighting 0 = none, 1 = full */
- 0.8, /* Cusp chroma alignment weighting 0 = none, 1 = full */
- 0.7 /* Cusp hue alignment weighting 0 = none, 1 = full */
+ -1.0, /* Cusp luminance alignment weighting 0 = none, 1 = full */
+ -1.0, /* Cusp chroma alignment weighting 0 = none, 1 = full */
+ 0.0 /* Cusp hue alignment weighting 0 = none, 1 = full */
},
- 1.15 /* Chroma expansion 1 = none */
+ -1.0, /* 2.0 Alignment twist power, 0 = linear, 1 = curve, 2+ late curve */
+ -1.0 /* Chroma expansion 1 = none */
},
{ /* Radial weighting */
-1.0, /* Radial error overall weight, 0 + */
@@ -283,7 +293,7 @@ gammapweights pweights[] = {
},
{ /* Weighting of absolute error of destination from source */
-1.0, /* Absolute error overall weight */
- -1.0, /* Hue dominance vs l+c, 0 - 1 */
+ 0.8, /* Hue dominance vs l+c, 0 - 1 */
-1.0, /* White l dominance vs, c, 0 - 1 */
-1.0, /* Grey l dominance vs, c, 0 - 1 */
@@ -296,7 +306,7 @@ gammapweights pweights[] = {
-1.0 /* L error xover threshold in DE */
},
{ /* Relative error preservation using smoothing */
- 20.0, 20.0 /* Relative Smoothing radius L* H* */
+ -1.0, 15.0 /* Relative Smoothing radius L* H* */
},
{ /* Weighting of excessive compression error, which is */
/* the src->dst vector length over the available dst depth. */
@@ -306,14 +316,15 @@ gammapweights pweights[] = {
-1.0 /* Expansion depth weight */
},
{
- 0.5 /* Fine tuning expansion weight, 0 - 1 */
+ -1.0 /* Fine tuning expansion weight, 0 - 1 */
}
},
+#endif /* NEVER */
{
gmm_end,
}
};
-double psmooth = 5.0; /* [5.0] Level of RSPL smoothing for perceptual, 1 = nominal */
+double psmooth = 4.0; /* [5.0] Level of RSPL smoothing for perceptual, 1 = nominal */
/* Saturation mapping weights, where saturation has priority over smoothness */
gammapweights sweights[] = {
@@ -325,6 +336,7 @@ gammapweights sweights[] = {
0.5, /* Cusp chroma alignment weighting 0 = none, 1 = full */
0.6 /* Cusp hue alignment weighting 0 = none, 1 = full */
},
+ 1.0, /* Alignment twist power, 0 = linear, 1 = curve, 2+ late curve */
1.05 /* Chroma expansion 1 = none */
},
{ /* Radial weighting */
@@ -347,7 +359,7 @@ gammapweights sweights[] = {
10.0 /* L error extra xover threshold in DE */
},
{ /* Relative vector smoothing */
- 15.0, 20.0 /* Relative Smoothing radius L* H* */
+ 20.0, 25.0 /* Relative Smoothing radius L* H* */
},
{ /* Weighting of excessive compression error, which is */
/* the src->dst vector length over the available dst depth. */
@@ -368,6 +380,7 @@ gammapweights sweights[] = {
1.0, /* Cusp chroma alignment weighting 0 = none, 1 = full */
1.0 /* Cusp hue alignment weighting 0 = none, 1 = full */
},
+ 1.0, /* Alignment twist power, 0 = linear, 1 = curve, 2+ late curve */
1.20 /* Chroma expansion 1 = none */
},
{ /* Radial weighting */
@@ -428,6 +441,7 @@ static void domap(gammap *s, double *out, double *in);
static void dopartialmap1(gammap *s, double *out, double *in);
static void dopartialmap2(gammap *s, double *out, double *in);
static gamut *parttransgamut(gammap *s, gamut *src);
+static void invdomap1(gammap *s, double *out, double *in);
#ifdef PLOT_GAMUTS
static void map_trans(void *cntx, double out[3], double in[3]);
#endif
@@ -487,7 +501,7 @@ gammap *new_gammap(
int j;
#if defined(PLOT_LMAP) || defined(PLOT_GAMUTS) || defined(PLOT_3DKNEES)
- fprintf(stderr,"##### A gammap.c PLOT is #defined ####\n");
+# pragma message("################ A gammap.c PLOT is #defined #########################")
#endif
if (verb) {
@@ -504,6 +518,7 @@ gammap *new_gammap(
/* Setup methods */
s->del = del_gammap;
s->domap = domap;
+ s->invdomap1 = invdomap1;
/* Now create everything */
@@ -898,10 +913,50 @@ glumknf = 1.0;
}
}
- /* To ensure symetry between compression and expansion, always create RSPL */
- /* for compression and its inverse, and then swap grey and igrey rspl to compensate. */
- if ((dwL - dbL) > (swL - sbL))
+#ifdef PLOT_LMAP
+ printf("sbL = %f, swL = %f\n",sbL,swL);
+ printf("dbL = %f, dwL = %f\n",dbL,dwL);
+#endif
+
+ /* Remember our source and destination mapping targets */
+ /* so that we can use them for fine tuning later. */
+
+ /* We scale the source and target white and black */
+ /* points to match the L values of the source and destination */
+ /* L curve mapping, as this is how we have chosen the */
+ /* white and black point mapping for the link. */
+ /* Put them back in pre-rotated space, so that we can */
+ /* check the overall transform of the white and black points. */
+ t = (swL - sr_cs_bp[0])/(sr_cs_wp[0] - sr_cs_bp[0]);
+ for (j = 0; j < 3; j++)
+ s_mt_wp[j] = sr_cs_bp[j] + t * (sr_cs_wp[j] - sr_cs_bp[j]);
+ icmMul3By3x4(s_mt_wp, s->igrot, s_mt_wp);
+
+ t = (sbL - sr_cs_wp[0])/(sr_cs_bp[0] - sr_cs_wp[0]);
+ for (j = 0; j < 3; j++)
+ s_mt_bp[j] = sr_cs_wp[j] + t * (sr_cs_bp[j] - sr_cs_wp[j]);
+//printf("~1 check black point rotated = %f %f %f\n",s_mt_bp[0],s_mt_bp[1],s_mt_bp[2]);
+ icmMul3By3x4(s_mt_bp, s->igrot, s_mt_bp);
+//printf("~1 check black point prerotated = %f %f %f\n",s_mt_bp[0],s_mt_bp[1],s_mt_bp[2]);
+
+ t = (dwL - dr_cs_bp[0])/(dr_cs_wp[0] - dr_cs_bp[0]);
+ for (j = 0; j < 3; j++)
+ d_mt_wp[j] = dr_cs_bp[j] + t * (dr_cs_wp[j] - dr_cs_bp[j]);
+
+ for (j = 0; j < 3; j++)
+ d_mt_bp[j] = dr_cs_wp[j] + t * (dr_cs_bp[j] - dr_cs_wp[j]);
+
+ /* To ensure symetry between compression and expansion, always create RSPL for */
+ /* overall compression and its inverse, and then swap grey and igrey rspl to compensate. */
+ /* We swap the source and desitination white and black points to achieve this. */
+ /* Note that we could still have expansion at one end or the other, depending */
+ /* on the center point location, so we need to allow for this in the rspl setup. */
+ if ((dwL - dbL) > (swL - sbL)) {
+ double tt;
+ tt = swL; swL = dwL; dwL = tt;
+ tt = sbL; sbL = dbL; dbL = tt;
revrspl = 1;
+ }
/* White point end */
lpnts[ngreyp].p[0] = swL;
@@ -913,9 +968,6 @@ glumknf = 1.0;
lpnts[ngreyp].v[0] = dbL;
lpnts[ngreyp++].w = 10.0; /* Must go through here */
-//printf("~1 white loc %f, val %f\n",swL,dwL);
-//printf("~1 black loc %f, val %f\n",sbL,dbL);
-
#ifdef USE_GLUMKNF
if (gmi->glumknf < 0.05)
#endif /* USE_GLUMKNF */
@@ -931,33 +983,42 @@ glumknf = 1.0;
#ifdef USE_GLUMKNF
else { /* There is at least some weight in knee points */
double cppos = 0.50; /* Center point ratio between black and white */
- double cplv; /* Center point location and value */
- double kppos = 0.30; /* Knee point ratio between white/black & center */
+ double cpll, cplv; /* Center point location and value */
+ double kpwpos = 0.30; /* White knee point location prop. towards center */
+ double kpbpos = 0.20; /* Black knee point location prop. towards center */
double kwl, kbl, kwv, kbv; /* Knee point values and locations */
double kwx, kbx; /* Knee point extra */
+#ifdef PLOT_LMAP
+ printf("%ssbL = %f, swL = %f\n", revrspl ? "(swapped) ": "", sbL,swL);
+ printf("%sdbL = %f, dwL = %f\n", revrspl ? "(swapped) ": "", dbL,dwL);
+#endif
-//printf("sbL = %f, swL = %f\n",sbL,swL);
-//printf("dbL = %f, dwL = %f\n",dbL,dwL);
-
- /* Center point */
+ /* Center point location */
+ cpll = cppos * (swL - sbL) + sbL;
+ // ~~?? would this be better if the output
+ // was scaled by dwL/swL ?
cplv = cppos * (swL - sbL) + sbL;
-//printf("~1 computed cplv = %f\n",cplv);
+#ifdef PLOT_LMAP
+ printf("cpll = %f, cplv = %f\n",cpll, cplv);
+#endif
#ifdef NEVER /* Don't use a center point */
- lpnts[ngreyp].p[0] = cplv;
+ lpnts[ngreyp].p[0] = cpll;
lpnts[ngreyp].v[0] = cplv;
- lpnts[ngreyp++].w = 0.5;
+ lpnts[ngreyp++].w = 5.0;
#endif
//printf("~1 black half diff = %f\n",dbL - sbL);
//printf("~1 white half diff = %f\n",dwL - swL);
/* Knee point locations */
- kwl = kppos * (cplv - swL) + swL;
- kbl = kppos * (cplv - sbL) + sbL;
+ kwl = kpwpos * (cplv - swL) + swL;
+ kbl = kpbpos * (cplv - sbL) + sbL;
/* Extra compression for white and black knees */
+ // ~~ ie move knee point level beyond 45 degree line
+ // ~~ weigting of black point and white point differences
kwx = 0.6 * (dbL - sbL) + 1.0 * (swL - dwL);
kbx = 1.0 * (dbL - sbL) + 0.6 * (swL - dwL);
@@ -975,47 +1036,22 @@ glumknf = 1.0;
kbv = dbL;
-//printf("~1 kbl = %f, kbv = %f\n",kbl, kbv);
-//printf("~1 kwl = %f, kwv = %f\n",kwl, kwv);
+#ifdef PLOT_LMAP
+ printf("using kbl = %f, kbv = %f\n",kbl, kbv);
+ printf("using kwl = %f, kwv = %f\n",kwl, kwv);
+#endif
- /* Emphasise points to cause "knee" curve */
+ /* Emphasise points to cause white "knee" curve */
lpnts[ngreyp].p[0] = kwl;
lpnts[ngreyp].v[0] = kwv;
lpnts[ngreyp++].w = gmi->glumknf * gmi->glumknf;
+ /* Emphasise points to cause black "knee" curve */
lpnts[ngreyp].p[0] = kbl;
lpnts[ngreyp].v[0] = kbv;
lpnts[ngreyp++].w = 1.5 * gmi->glumknf * 1.5 * gmi->glumknf;
}
#endif /* USE_GLUMKNF */
-
- /* Remember our source and destinatio mapping targets */
- /* so that we can use them for fine tuning later. */
-
- /* We scale the source and target white and black */
- /* points to match the L values of the source and destination */
- /* L curve mapping, as this is how we have chosen the */
- /* white and black point mapping for the link. */
- /* Put them back in pre-rotated space, so that we can */
- /* check the overall transform of the white and black points. */
- t = (swL - sr_cs_bp[0])/(sr_cs_wp[0] - sr_cs_bp[0]);
- for (j = 0; j < 3; j++)
- s_mt_wp[j] = sr_cs_bp[j] + t * (sr_cs_wp[j] - sr_cs_bp[j]);
- icmMul3By3x4(s_mt_wp, s->igrot, s_mt_wp);
-
- t = (sbL - sr_cs_wp[0])/(sr_cs_bp[0] - sr_cs_wp[0]);
- for (j = 0; j < 3; j++)
- s_mt_bp[j] = sr_cs_wp[j] + t * (sr_cs_bp[j] - sr_cs_wp[j]);
-//printf("~1 check black point rotated = %f %f %f\n",s_mt_bp[0],s_mt_bp[1],s_mt_bp[2]);
- icmMul3By3x4(s_mt_bp, s->igrot, s_mt_bp);
-//printf("~1 check black point prerotated = %f %f %f\n",s_mt_bp[0],s_mt_bp[1],s_mt_bp[2]);
-
- t = (dwL - dr_cs_bp[0])/(dr_cs_wp[0] - dr_cs_bp[0]);
- for (j = 0; j < 3; j++)
- d_mt_wp[j] = dr_cs_bp[j] + t * (dr_cs_wp[j] - dr_cs_bp[j]);
-
- for (j = 0; j < 3; j++)
- d_mt_bp[j] = dr_cs_wp[j] + t * (dr_cs_bp[j] - dr_cs_wp[j]);
}
/* We now create the 1D rspl L map, that compresses or expands the luminence */
@@ -1031,15 +1067,6 @@ glumknf = 1.0;
double avgdev[MXDO];
int gres = 256;
- if (revrspl) { /* Invert creation and usage for symetry between compress and exp. */
- int i;
- for (i = 0; i < ngreyp; i++) {
- double tt = lpnts[i].p[0]; /* Swap source and dest */
- lpnts[i].p[0] = lpnts[i].v[0];
- lpnts[i].v[0] = tt;
- }
- }
-
/* Create a 1D rspl, that is used to */
/* form the overall L compression mapping. */
if ((s->grey = new_rspl(RSPL_NOFLAGS, 1, 1)) == NULL) /* Allocate 1D -> 1D */
@@ -1076,7 +1103,7 @@ glumknf = 1.0;
/* Create it from inverse lookups of s->grey */
s->igrey->set_rspl(s->igrey, 0, (void *)s->grey, inv_grey_func, il, ih, &gres, ol, oh);
- if (revrspl) { /* Swap to compensate for expansion */
+ if (revrspl) { /* Swap to compensate for swapping of white and black points */
rspl *tt = s->grey;
s->grey = s->igrey;
s->igrey = tt;
@@ -1140,6 +1167,7 @@ glumknf = 1.0;
/* if there is any compression or expansion to do. */
if (gmi->gamcpf > 1e-6 || gmi->gamexf > 1e-6) {
cow *gpnts = NULL; /* Mapping points to create gamut mapping */
+ int max_gpnts;
int nspts; /* Number of source gamut surface points */
int rgridpts; /* Number of range surface grid points */
int i, j;
@@ -1175,7 +1203,8 @@ typedef struct {
}
#endif
- if ((gpnts = (cow *)malloc((nres + 3 * nspts + rgridpts) * sizeof(cow))) == NULL) {
+ max_gpnts = nres + 3 * nspts + rgridpts;
+ if ((gpnts = (cow *)malloc(max_gpnts * sizeof(cow))) == NULL) {
fprintf(stderr,"gamut map: Malloc of mapping setup points failed\n");
s->grey->del(s->grey);
s->igrey->del(s->igrey);
@@ -1275,6 +1304,8 @@ typedef struct {
gpnts[ngamp].w);
#endif
ngamp++;
+ if (ngamp >= max_gpnts)
+ error("gammap: internal, not enough space for mapping points A (%d > %d)\n",ngamp, max_gpnts);
}
#endif /* USE_GREYMAP */
@@ -1436,10 +1467,10 @@ typedef struct {
doaxes = 1;
#endif
if (diagname != NULL)
- wrl = new_vrml(diagname, doaxes, 0);
+ wrl = new_vrml(diagname, doaxes, vrml_lab);
#ifdef PLOT_DIAG_WRL
else
- wrl = new_vrml("gammap.wrl", doaxes, 0);
+ wrl = new_vrml("gammap", doaxes, vrml_lab);
#endif
}
@@ -1513,31 +1544,51 @@ typedef struct {
}
gpnts[ngamp++].w = 1.01; /* Main gamut surface mapping point */
/* (Use 1.01 as a marker value) */
+ if (ngamp >= max_gpnts)
+ error("gammap: internal, not enough space for mapping points B (%d > %d)\n",ngamp, max_gpnts);
#ifdef USE_GAMKNF
/* Add sub surface mapping point if available */
if (nsm[i].vflag != 0) { /* Sub surface point is available */
/* Compute destination value which is a blend */
- /* between the source value and the fully mapped destination value. */
+ /* between the source value and the knee adjusted destination */
icmBlend3(nsm[i].div2, nsm[i].sv2, nsm[i].dv2, cpexf);
#ifdef NEVER
printf("Src2 point = %f %f %f radius %f\n",nsm[i].sv2[0], nsm[i].sv2[1], nsm[i].sv2[2], nsm[i].sr);
printf("Dst2 point = %f %f %f radius %f\n",nsm[i].dv2[0], nsm[i].dv2[1], nsm[i].dv2[2], nsm[i].dr);
printf("Blended dst2 point = %f %f %f\n",nsm[i].div2[0], nsm[i].div2[1], nsm[i].div2[2]);
+ printf("Src/Dst3 point = %f %f %f w %f\n",nsm[i].sd2[0], nsm[i].sd2[1], nsm[i].sd2[2]);
printf("\n");
#endif /* NEVER */
+
/* Set the sub-surface gamut hull mapping point */
for (j = 0; j < 3; j++) {
gpnts[ngamp].p[j] = nsm[i].sv2[j];
gpnts[ngamp].v[j] = nsm[i].div2[j];
}
gpnts[ngamp++].w = nsm[i].w2; /* Sub-suface mapping points */
+
+ if (ngamp >= max_gpnts)
+ error("gammap: internal, not enough space for mapping points C (%d > %d)\n",ngamp, max_gpnts);
+
+ /* Set the sub-surface gamut hull mapping point */
+ for (j = 0; j < 3; j++) {
+ gpnts[ngamp].p[j] = nsm[i].sd3[j];
+ gpnts[ngamp].v[j] = nsm[i].sd3[j];
+ }
+ gpnts[ngamp++].w = nsm[i].w3; /* Sub-suface mapping points */
+
+ if (ngamp >= max_gpnts)
+ error("gammap: internal, not enough space for mapping points D (%d > %d)\n",ngamp, max_gpnts);
}
#endif /* USE_GAMKNF */
}
+ if (ngamp >= max_gpnts)
+ error("gammap: internal, not enough space for mapping points (%d > %d)\n",ngamp, max_gpnts);
+
/* Create preliminary gamut mapping rspl, without grid boundary values. */
/* We use this to lookup the mapping for points on the source space gamut */
/* that result from clipping our grid boundary points */
@@ -1601,6 +1652,9 @@ typedef struct {
/* A low weight seems to be enough ? */
/* the lower the better in terms of geting best hull mapping fidelity */
gpnts[ngamp++].w = 0.05 * ww;
+
+ if (ngamp >= max_gpnts)
+ error("gammap: internal, not enough space for mapping points E (%d > %d)\n",ngamp, max_gpnts);
}
DC_INC(gc);
if (DC_DONE(gc))
@@ -1833,11 +1887,11 @@ typedef struct {
/* Add the source and dest gamut surfaces */
#ifdef PLOT_SRC_GMT
- wrl->make_gamut_surface_2(wrl, sil_gam, 0.6, 0, cc);
+ wrl->make_gamut_surface_2(wrl, sil_gam, 0.6, 0, cc); /* Grey */
#endif /* PLOT_SRC_GMT */
#ifdef PLOT_DST_GMT
cc[0] = -1.0;
- wrl->make_gamut_surface(wrl, d_gam, 0.2, cc);
+ wrl->make_gamut_surface(wrl, d_gam, 0.3, cc); /* Natural color */
#endif /* PLOT_DST_GMT */
#ifdef PLOT_DIGAM
if (nsm[0].dgam == NULL)
@@ -1918,7 +1972,6 @@ typedef struct {
# ifdef SHOW_SUB_SURF
if (nsm[i].vflag != 0) { /* Sub surface point is available */
-
wrl->add_col_vertex(wrl, 0, nsm[i].sv2, lgrey); /* Subs-surf Source value */
wrl->add_col_vertex(wrl, 0, nsm[i].div2, purp); /* Blended destination value */
}
@@ -1928,14 +1981,29 @@ typedef struct {
wrl->make_lines(wrl, 0, 2); /* Guide vectors */
#endif /* Show vectors */
-#ifdef SHOW_VECTOR_INDEXES
+#if defined(SHOW_VECTOR_INDEXES) || defined(SHOW_SUB_PNTS)
for (i = 0; i < nnsm; i++) {
- double cream[3] = { 0.7, 0.7, 0.5 };
- char buf[100];
- sprintf(buf, "%d", i);
- wrl->add_text(wrl, buf, nsm[i].sv, cream, 0.5);
- }
+#ifdef SHOW_VECTOR_INDEXES
+ {
+ double cream[3] = { 0.7, 0.7, 0.5 };
+ char buf[100];
+ sprintf(buf, "%d", i);
+ wrl->add_text(wrl, buf, nsm[i].sv, cream, 0.5);
+ }
#endif /* SHOW_VECTOR_INDEXES */
+# ifdef SHOW_SUB_PNTS
+ if (nsm[i].vflag != 0) { /* Sub surface point is available */
+ double red[3] = { 1.0, 0.0, 0.0 };
+ double green[3] = { 0.0, 1.0, 0.0 };
+ double yellow[3] = { 1.0, 1.0, 0.0 };
+
+ wrl->add_marker(wrl, nsm[i].sv2, red, 1.0); /* Subs-surf Source value */
+ wrl->add_marker(wrl, nsm[i].div2, green, 1.0); /* Blended destination value */
+ wrl->add_marker(wrl, nsm[i].sd3, yellow, 1.0); /* Deep sub-surface point */
+ }
+# endif /* SHOW_SUB_PNTS */
+ }
+#endif
/* add the locus from locus.ts file */
if (locus != NULL) {
@@ -2184,10 +2252,10 @@ typedef struct {
}
#ifdef PLOT_GAMUTS
- scl_gam->write_vrml(scl_gam, "src.wrl", 1, 0);
- sil_gam->write_vrml(sil_gam, "img.wrl", 1, 0);
- d_gam->write_vrml(d_gam, "dst.wrl", 1, 0);
- sc_gam->write_trans_vrml(sc_gam, "gmsrc.wrl", 1, 0, map_trans, s);
+ scl_gam->write_vrml(scl_gam, "src", 1, 0);
+ sil_gam->write_vrml(sil_gam, "img", 1, 0);
+ d_gam->write_vrml(d_gam, "dst", 1, 0);
+ sc_gam->write_trans_vrml(sc_gam, "gmsrc", 1, 0, map_trans, s);
#endif
if (sil_gam != scl_gam)
@@ -2222,6 +2290,8 @@ gammap *s
free(s);
}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
/* Apply the gamut mapping to the given color value */
static void domap(
gammap *s,
@@ -2336,6 +2406,51 @@ double *in
}
}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/* powell function - minimise error to target */
+static double invgmfunc(
+void *fdata,
+double *tp
+) {
+ gammap *s = (gammap *)fdata;
+ int i;
+ double gmv[3];
+ double tt, rv = 0.0;
+
+ domap(s, gmv, tp);
+ for (i = 0; i < 3; i++) {
+ double tt = gmv[i] - s->tv[i];
+ rv += tt * tt;
+ }
+
+ return rv;
+}
+
+/* Invert a gamut mapping using powell */
+static void invdomap1(
+gammap *s,
+double *out,
+double *in
+) {
+ double ss[3] = { 20.0, 20.0, 20.0 }; /* search area */
+ double tp[3], rv;
+
+ s->tv[0] = tp[0] = in[0];
+ s->tv[1] = tp[1] = in[1];
+ s->tv[2] = tp[2] = in[2];
+
+ if (powell(&rv, 3, tp, ss, 1e-7, 5000, invgmfunc, (void *)s, NULL, NULL) != 0) {
+ warning("gamut invdomap1 failed on %f %f %f\n", in[0], in[1], in[2]);
+ }
+
+ out[0] = tp[0];
+ out[1] = tp[1];
+ out[2] = tp[2];
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
/* Function to pass to rspl to invert grey curve */
static void inv_grey_func(
void *cntx,
diff --git a/gamut/gammap.h b/gamut/gammap.h
index 3bc1c8c..69207a4 100644
--- a/gamut/gammap.h
+++ b/gamut/gammap.h
@@ -31,11 +31,13 @@ struct _gammap {
rspl *map; /* Rotated, L mapped Lab -> Lab gamut map */
double imin[3], imax[3]; /* Input range limits of map */
+ double tv[3]; /* Inversion target value */
/* Public: */
/* Methods */
void (*del)(struct _gammap *s); /* Free ourselves */
void (*domap)(struct _gammap *s, double *out, double *in); /* Do the mapping */
+ void (*invdomap1)(struct _gammap *s, double *out, double *in); /* Do the inverse mapping */
}; typedef struct _gammap gammap;
diff --git a/gamut/gamut.c b/gamut/gamut.c
index 09a5110..02b18dc 100644
--- a/gamut/gamut.c
+++ b/gamut/gamut.c
@@ -50,22 +50,22 @@
#define COLORED_VRML
-#define DO_TWOPASS /* Second pass with adjustment based on first pass */
+#define DO_TWOPASS /* [def] Second pass with adjustment based on first pass */
-#define FAKE_SEED_SIZE 0.1 /* Usually 0.1 */
-#define TRIANG_TOL 1e-10 /* Triangulation tollerance, usually 1e-10 */
+#define FAKE_SEED_SIZE 0.1 /* [0.1] */
+#define TRIANG_TOL 1e-10 /* [1e-10] Triangulation tollerance */
-#define NORM_LOG_POW 0.25 /* Normal, colorspace lopow value */
-#define RAST_LOG_POW 0.05 /* Raster lopow value */
+#define NORM_LOG_POW 0.25 /* [0.25] Normal, colorspace lopow value */
+#define RAST_LOG_POW 0.05 /* [0.05] Raster lopow value */
#undef TEST_CONVEX_HULL /* Use pure convex hull, not log hull */
-#undef DEBUG_TRIANG /* Enable detailed triangulation debugging */
-#undef DEBUG_TRIANG_VRML /* Create debug.wrl for each step of triangulation */
- /* (Only on second pass if #define DO_TWOPASS) */
+#undef DEBUG_TRIANG /* Enable detailed triangulation debugging & diag2 */
+#undef DEBUG_TRIANG_VRML /* Create diag1 vis & diag2 vis for each step */
+ /* of triangulation (Only on second pass if #define DO_TWOPASS) */
#undef DEBUG_TRIANG_VRML_STEP /* Wait for return after each step */
-#undef DEBUG_SPLIT_VRML /* Create debug.wrl for each step of triangle plane split */
+#undef DEBUG_SPLIT_VRML /* Create diag3 vis for each step of triangle plane split */
#undef TEST_LOOKUP
#undef TEST_NEAREST
@@ -77,7 +77,8 @@
#undef ASSERTS /* Do internal checking */
-#undef INTERSECT_DEBUG /* Turn on compute_vector_isect debugging, inc isect.wrl plot */
+#undef INTERSECT_DEBUG /* Turn on compute_vector_isect debugging, */
+ /* and isect & isect2 vis plot if deb_insect set to 1 */
#undef INTERSECT_VERIFY /* Verify compute_vector_isect against brute force search */
/* These routines support:
@@ -2327,7 +2328,7 @@ gtri *tp /* Triangle faces to be added */
add_to_hit_list(s, hlp, t2); /* Add edge 2 to hit list */
}
-#ifdef DEBUG_TRIANG
+#if defined(DEBUG_TRIANG) || defined(DEBUG_TRIANG_VRML)
typedef struct {
int tix[3]; /* Triangle indexes */
int type; /* 0 = hit, 1 = added */
@@ -2343,7 +2344,7 @@ gvert *v /* Vertex to insert */
gtri *hl; /* Triangle face hit list (polygon faces) */
double tol = TRIANG_TOL;
int hit = 0; /* Vertex expands hull flag */
-#ifdef DEBUG_TRIANG
+#if defined(DEBUG_TRIANG) || defined(DEBUG_TRIANG_VRML)
int intri = 0; /* Vertex landed in a triangle */
XLIST(tidxs, hittris)
tidxs xxs;
@@ -2379,7 +2380,7 @@ gvert *v /* Vertex to insert */
/* If vertex is above the log hull surface, add triangle to the hit list. */
if (c < -tol) {
-#ifdef DEBUG_TRIANG
+#if defined(DEBUG_TRIANG) || defined(DEBUG_TRIANG_VRML)
int j;
double bds = -1e10;
#endif
@@ -2390,7 +2391,7 @@ gvert *v /* Vertex to insert */
tp->n, tp->v[0]->n, tp->v[1]->n, tp->v[2]->n,c);
#endif
-#ifdef DEBUG_TRIANG
+#if defined(DEBUG_TRIANG) || defined(DEBUG_TRIANG_VRML)
for (j = 0; j < 3; j++) {
double ds;
ds = tp->ee[j][0] * v->ch[0]
@@ -2398,14 +2399,18 @@ gvert *v /* Vertex to insert */
+ tp->ee[j][2] * v->ch[2]
+ tp->ee[j][3];
if (ds > tol) {
+#ifdef DEBUG_TRIANG
printf("Vertex is not in triangle by %e\n",ds);
+#endif
break;
}
if (ds > bds)
bds = ds;
}
if (j >= 3) {
+#ifdef DEBUG_TRIANG
printf("Vertex is in triangle by %e\n",bds);
+#endif
intri = 1; /* Landed in this triangle */
}
@@ -2458,7 +2463,7 @@ if (!intri) printf("~1 ###### vertex didn't land in any triangle! ########\n");
xtp = tp->e[0]->t[1];
//printf("Got a hit on triangle %d: %d %d %d\n", xtp->n, xtp->v[0]->n, xtp->v[1]->n, xtp->v[2]->n);
-#ifdef DEBUG_TRIANG
+#if defined(DEBUG_TRIANG) || defined(DEBUG_TRIANG_VRML)
xxs.tix[0] = xtp->v[0]->n, xxs.tix[1] = xtp->v[1]->n, xxs.tix[2] = xtp->v[2]->n;
xxs.type = 1;
XLIST_ADD(&hittris, xxs)
@@ -2472,8 +2477,13 @@ if (!intri) printf("~1 ###### vertex didn't land in any triangle! ########\n");
}
#ifdef DEBUG_TRIANG_VRML
- write_diag_vrml(s, v->ch, hittris.no, hittris.list, hl);
-#endif
+#ifdef DO_TWOPASS
+ if (s->pass > 0)
+#endif /* DO_TWOPASS */
+ {
+ write_diag_vrml(s, v->ch, hittris.no, hittris.list, hl); /* diag1 triang hit */
+ }
+#endif /* DEBUG_TRIANG_VRML */
//printf("About to turn polygon faces into triangles\n");
/* Turn all the faces that made it to the */
@@ -2509,7 +2519,11 @@ if (!intri) printf("~1 ###### vertex didn't land in any triangle! ########\n");
//printf("~1 Creating new triangle %d: %d %d %d\n", tp->n, tp->v[0]->n, tp->v[1]->n, tp->v[2]->n);
} END_FOR_ALL_ITEMS(tp);
-#ifdef DEBUG_TRIANG_VRML
+#if defined(DEBUG_TRIANG) || defined(DEBUG_TRIANG_VRML)
+#ifdef DO_TWOPASS
+ if (s->pass > 0)
+#endif /* DO_TWOPASS */
+ {
tp = hl;
hittris.no = 0;
FOR_ALL_ITEMS(gtri, tp) {
@@ -2517,14 +2531,13 @@ if (!intri) printf("~1 ###### vertex didn't land in any triangle! ########\n");
xxs.type = 2;
XLIST_ADD(&hittris, xxs)
} END_FOR_ALL_ITEMS(tp);
- write_diag_vrml(s, v->ch, hittris.no, hittris.list, NULL);
+ write_diag_vrml(s, v->ch, hittris.no, hittris.list, NULL); /* diag2 */
#ifdef DEBUG_TRIANG_VRML_STEP
-#ifdef DO_TWOPASS
- if (s->pass > 0)
-#endif /* DO_TWOPASS */
+ printf("Waiting for return key after diag1%s and diag1%s\n",vrml_ext(),vrml_ext());
getchar();
#endif
-#endif
+ }
+#endif /* DEBUG_TRIANG_VRML || DEBUG_TRIANG_VRML */
/* Move them to the triangulation. */
tp = hl;
@@ -2542,8 +2555,13 @@ if (!intri) printf("~1 ###### vertex didn't land in any triangle! ########\n");
v->f &= ~GVERT_INSIDE; /* and it's not inside */
}
-#ifdef DEBUG_TRIANG
+#if defined(DEBUG_TRIANG) || defined(DEBUG_TRIANG_VRML)
+#ifdef DO_TWOPASS
+ if (s->pass > 0)
+#endif /* DO_TWOPASS */
+ {
XLIST_FREE(&hittris);
+ }
#endif
}
@@ -3498,7 +3516,7 @@ double *in /* input point (absolute)*/
rv = radial_point(s, s->lutree, nin);
if (rv < 0.0) {
- error("gamut: radial internal error - failed to find triangle\n");
+ error("gamut: radial internal error - failed to find triangle (rv %f)\n",rv);
}
if (out != NULL) {
@@ -3753,7 +3771,8 @@ int llen /* Number of triangles in the list */
}
#ifdef DEBUG_SPLIT_VRML
- write_split_diag_vrml(s, list, llen);
+ write_split_diag_vrml(s, list, llen); /* diag3.wrl/xdom/x3dom */
+ printf("Waiting for return key after diag3%s:\n",vrml_ext());
getchar();
#endif /* DEBUG_SPLIT_VRML */
@@ -3904,14 +3923,14 @@ double *nin /* Normalised center relative point */
/* Return the location on the surface of the triangle */
/* that is intersected by the radial direction */
/* of the given relative point. Return the distance to */
-/* the gamut surface. */
+/* the gamut surface. Return < 0.0 on fail. */
static double radial_point(
gamut *s,
gbsp *np, /* BSP node pointer we're at */
double *nin /* Normalised center relative point */
) {
gtri *t;
- double rv;
+ double rv, num, denom;
//if (trace) printf("~1 radial_point: BSP 0x%x tag = %d, point %f %f %f\n", np,np->tag,nin[0],nin[1],nin[2]);
@@ -3925,8 +3944,14 @@ double *nin /* Normalised center relative point */
/* Compute the intersection of the input vector with the triangle plane */
/* (Since nin[] is already relative, we don't need to subtract cent[] from it) */
- rv = -(t->pe[0] * s->cent[0] + t->pe[1] * s->cent[1] + t->pe[2] * s->cent[2] + t->pe[3])/
- (t->pe[0] * nin[0] + t->pe[1] * nin[1] + t->pe[2] * nin[2]);
+ num = -(t->pe[0] * s->cent[0] + t->pe[1] * s->cent[1] + t->pe[2] * s->cent[2] + t->pe[3]);
+ denom = (t->pe[0] * nin[0] + t->pe[1] * nin[1] + t->pe[2] * nin[2]);
+
+ if (fabs(denom) < 1e-9) {
+ /* Hmm. The ray is paralell to the triangle ? */
+ error("radial_point: failed to intersect radial triangle\n");
+ }
+ rv = num/denom;
#ifdef ASSERTS
/* check the result */
@@ -4809,7 +4834,7 @@ gtri **omxtri
#define ISDBG(xxx) if (deb_insect) printf xxx
-int deb_insect = 0; /* Do vrml plot */
+int deb_insect = 1; /* Do vrml plot */
/* Debug - given a BSP node, add all the triangles vertexes indexes */
/* below this node to the diagnosti wrl */
@@ -4886,6 +4911,8 @@ int *lu /* Number used in list */
#endif
#ifdef INTERSECT_DEBUG
if (deb_insect) {
+ char isect[20] = "isect";
+ char isect2[20] = "isect2";
vrml *wrl = NULL;
double cc[3] = { 1.0, 1.0, 0.0 };
double red[3] = { 1.0, 0.0, 0.0 };
@@ -4894,10 +4921,13 @@ int *lu /* Number used in list */
double p1[3], p2[3];
int i;
- unlink("isect2.wrl");
- rename("isect.wrl", "isect2.wrl");
+ strcat(isect2, vrml_ext());
+ strcat(isect, vrml_ext());
+
+ unlink(isect2);
+ rename(isect, isect2);
- if ((wrl = new_vrml("isect.wrl", 0)) == NULL)
+ if ((wrl = new_vrml("isect", 0, vrml_lab)) == NULL)
error("New vrml failed");
/* The triangles below the BSP */
@@ -4946,9 +4976,8 @@ int *lu /* Number used in list */
wrl->add_marker(wrl, p2, blue, 0.5);
wrl->del(wrl);
- printf("Waiting for input after writing 'isect.wrl':\n");
+ printf("Waiting for input after writing '%s':\n", isect);
getchar();
-
}
#endif
@@ -5772,22 +5801,22 @@ int ll /* Size of list. */
#endif /* INTERSECT_DEBUG */
/* ===================================================== */
-/* Write to a VRML .wrl file */
+/* Write to a VRML/X3d file */
/* Return non-zero on error */
static int write_vrml(
gamut *s,
-char *filename,
+char *filename, /* Extension will be set automatically */
int doaxes, /* Non-zero if axes are to be written */
int docusps /* Non-zero if cusp points are to be marked */
) {
return write_trans_vrml(s, filename, doaxes, docusps, NULL, NULL);
}
-/* Write to a VRML .wrl file */
+/* Write to a VRML/X3d file */
/* Return non-zero on error */
static int write_trans_vrml(
gamut *s,
-char *filename,
+char *filename, /* Extension will be set automatically */
int doaxes, /* Non-zero if axes are to be written */
int docusps, /* Non-zero if cusp points are to be marked */
void (*transform)(void *cntx, double out[3], double in[3]), /* Optional transformation callback */
@@ -5795,123 +5824,19 @@ void *cntx
) {
int i;
gtri *tp; /* Triangle pointer */
- FILE *wrl;
- struct {
- double x, y, z;
- double wx, wy, wz;
- double r, g, b;
- } axes[5] = {
- { 0 - s->cent[1], 0 - s->cent[2], 50 - s->cent[0], 2, 2, 100, .7, .7, .7 },
- /* L axis */
- { 50 - s->cent[1], 0 - s->cent[2], 0 - s->cent[0], 100, 2, 2, 1, 0, 0 },
- /* +a (red) axis */
- { 0 - s->cent[1], -50 - s->cent[2], 0 - s->cent[0], 2, 100, 2, 0, 0, 1 },
- /* -b (blue) axis */
- { -50 - s->cent[1], 0 - s->cent[2], 0 - s->cent[0], 100, 2, 2, 0, 1, 0 },
- /* -a (green) axis */
- { 0 - s->cent[1], 50 - s->cent[2], 0 - s->cent[0], 2, 100, 2, 1, 1, 0 },
- /* +b (yellow) axis */
- };
-
- /* Define the labels */
- struct {
- double x, y, z;
- double size;
- char *string;
- double r, g, b;
- } labels[6] = {
- { -2 - s->cent[1], 2 - s->cent[2], - s->cent[0] + 100 + 10, 10, "+L*", .7, .7, .7 },
- /* Top of L axis */
- { -2 - s->cent[1], 2 - s->cent[2], - s->cent[0] - 10, 10, "0", .7, .7, .7 },
- /* Bottom of L axis */
- { 100 + 5 - s->cent[1], -3 - s->cent[2], 0 - s->cent[0], 10, "+a*", 1, 0, 0 },
- /* +a (red) axis */
- { -5 - s->cent[1], -100 - 10 - s->cent[2], 0 - s->cent[0], 10, "-b*", 0, 0, 1 },
- /* -b (blue) axis */
- { -100 - 15 - s->cent[1], -3 - s->cent[2], 0 - s->cent[0], 10, "-a*", 0, 0, 1 },
- /* -a (green) axis */
- { -5 - s->cent[1], 100 + 5 - s->cent[2], 0 - s->cent[0], 10, "+b*", 1, 1, 0 },
- /* +b (yellow) axis */
- };
+ vrml *wrl;
if IS_LIST_EMPTY(s->tris)
triangulate(s);
- if ((wrl = fopen(filename,"w")) == NULL) {
- fprintf(stderr,"Error opening output file '%s'\n",filename);
+ if ((wrl = new_vrml(filename, doaxes, vrml_lab)) == NULL) {
+ fprintf(stderr,"Error creating %s output '%s%s'\n",vrml_format(),filename,vrml_ext());
return 2;
}
- /* Spit out a VRML 2 Object surface of gamut */
-
- fprintf(wrl,"#VRML V2.0 utf8\n");
- fprintf(wrl,"\n");
- fprintf(wrl,"# Created by the Argyll CMS\n");
- fprintf(wrl,"Transform {\n");
- fprintf(wrl,"children [\n");
- fprintf(wrl," NavigationInfo {\n");
- fprintf(wrl," type \"EXAMINE\" # It's an object we examine\n");
- fprintf(wrl," } # We'll add our own light\n");
- fprintf(wrl,"\n");
- fprintf(wrl," DirectionalLight {\n");
- fprintf(wrl," intensity 0.2\n");
- fprintf(wrl," ambientIntensity 0.1\n");
- fprintf(wrl," direction -1 -1 -1\n");
- fprintf(wrl," }\n");
- fprintf(wrl," DirectionalLight {\n");
- fprintf(wrl," intensity 0.6\n");
- fprintf(wrl," ambientIntensity 0.2\n");
- fprintf(wrl," direction 1 1 1\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- fprintf(wrl," Viewpoint {\n");
- fprintf(wrl," position 0 0 250 # Position we view from\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- if (doaxes != 0) {
- fprintf(wrl,"# Lab axes as boxes:\n");
- for (i = 0; i < 5; i++) {
- fprintf(wrl,"Transform { translation %f %f %f\n", axes[i].x, axes[i].y, axes[i].z);
- fprintf(wrl,"\tchildren [\n");
- fprintf(wrl,"\t\tShape {\n");
- fprintf(wrl,"\t\t\tgeometry Box { size %f %f %f }\n",
- axes[i].wx, axes[i].wy, axes[i].wz);
- fprintf(wrl,"\t\t\tappearance Appearance { material Material ");
- fprintf(wrl,"{ diffuseColor %f %f %f} }\n", axes[i].r, axes[i].g, axes[i].b);
- fprintf(wrl,"\t\t}\n");
- fprintf(wrl,"\t]\n");
- fprintf(wrl,"}\n");
- }
- fprintf(wrl,"# Axes identification:\n");
- for (i = 0; i < 6; i++) {
- fprintf(wrl,"Transform { translation %f %f %f\n", labels[i].x, labels[i].y, labels[i].z);
- fprintf(wrl,"\tchildren [\n");
- fprintf(wrl,"\t\tShape {\n");
- fprintf(wrl,"\t\t\tgeometry Text { string [\"%s\"]\n",labels[i].string);
- fprintf(wrl,"\t\t\t\tfontStyle FontStyle { family \"SANS\" style \"BOLD\" size %f }\n",
- labels[i].size);
- fprintf(wrl,"\t\t\t\t}\n");
- fprintf(wrl,"\t\t\tappearance Appearance { material Material ");
- fprintf(wrl,"{ diffuseColor %f %f %f} }\n", labels[i].r, labels[i].g, labels[i].b);
- fprintf(wrl,"\t\t}\n");
- fprintf(wrl,"\t]\n");
- fprintf(wrl,"}\n");
- }
- fprintf(wrl,"\n");
- }
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation 0 0 0\n");
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry IndexedFaceSet {\n");
- fprintf(wrl," ccw FALSE\n");
- fprintf(wrl," convex TRUE\n");
- fprintf(wrl,"\n");
- fprintf(wrl," coord Coordinate { \n");
- fprintf(wrl," point [ # Verticy coordinates\n");
+ wrl->start_line_set(wrl, 0);
/* Spit out the point values, in order. */
- /* Note that a->x, b->y, L->z */
for (i = 0; i < s->nv; i++) {
double out[3];
@@ -5934,34 +5859,35 @@ void *cntx
rr[1] = s->verts[i]->hc - 0.5 * s->verts[i]->w;
rr[2] = s->verts[i]->vc - 0.5 * s->verts[i]->h;
gamut_radial2rect(s, cc, rr);
- fprintf(wrl,"%f %f %f,\n",cc[1], cc[2], cc[0]);
+ wrl->add_vertex(wrl, 0, cc);
rr[1] = s->verts[i]->hc - 0.5 * s->verts[i]->w;
rr[2] = s->verts[i]->vc + 0.5 * s->verts[i]->h;
gamut_radial2rect(s, cc, rr);
- fprintf(wrl,"%f %f %f,\n",cc[1], cc[2], cc[0]);
+ wrl->add_vertex(wrl, 0, cc);
rr[1] = s->verts[i]->hc + 0.5 * s->verts[i]->w;
rr[2] = s->verts[i]->vc + 0.5 * s->verts[i]->h;
gamut_radial2rect(s, cc, rr);
- fprintf(wrl,"%f %f %f,\n",cc[1], cc[2], cc[0]);
+ wrl->add_vertex(wrl, 0, cc);
rr[1] = s->verts[i]->hc + 0.5 * s->verts[i]->w;
rr[2] = s->verts[i]->vc - 0.5 * s->verts[i]->h;
gamut_radial2rect(s, cc, rr);
- fprintf(wrl,"%f %f %f,\n",cc[1], cc[2], cc[0]);
+ wrl->add_vertex(wrl, 0, cc);
}
#else /* Show point data */
# ifdef SHOW_SPHERE /* Show surface on sphere */
- fprintf(wrl,"%f %f %f,\n",s->verts[i]->sp[1], s->verts[i]->sp[2],
- s->verts[i]->sp[0]);
-# else
-# ifdef SHOW_HULL_PNTS
- fprintf(wrl,"%f %f %f,\n",s->verts[i]->ch[1], s->verts[i]->ch[2],
- s->verts[i]->ch[0]);
+ wrl->add_vertex(wrl, 0, s->verts[i]->sp);
# else
+# ifdef SHOW_HULL_PNTS
+ out[0] = s->verts[i]->ch[0] + s->cent[0];
+ out[1] = s->verts[i]->ch[1] + s->cent[1];
+ out[2] = s->verts[i]->ch[2] + s->cent[2];
+ wrl->add_vertex(wrl, 0, out);
+# else
/* Show normal gamut surface */
out[0] = s->verts[i]->p[0];
out[1] = s->verts[i]->p[1];
@@ -5970,99 +5896,61 @@ void *cntx
if (transform)
transform(cntx, out, out); /* Do transform */
- fprintf(wrl,"%f %f %f,\n",out[1]-s->cent[1], out[2]-s->cent[2], out[0]-s->cent[0]);
+ wrl->add_vertex(wrl, 0, out);
-# endif /* SHOW_HULL_PNTS */
+# endif /* SHOW_HULL_PNTS */
# endif /* SHOW_SPHERE */
#endif /* SHOW_BUCKETS */
}
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- fprintf(wrl," coordIndex [ # Indexes of poligon Verticies \n");
#ifdef SHOW_BUCKETS /* Show vertex buckets as surface */
for (i = 0; i < s->nv; i++) {
int j = s->verts[i]->sn;
+ int ix[4];
if (!(s->verts[i]->f & GVERT_SET))
continue;
- fprintf(wrl,"%d, %d, %d, %d, -1\n", j * 4, j * 4 + 1, j * 4 + 2, j * 4 + 3);
+ ix[0] = j * 4;
+ ix[1] = j * 4 + 1;
+ ix[2] = j * 4 + 2;
+ ix[3] = j * 4 + 3;
+ wrl->add_quad(wrl, 0, ix);
}
#else /* Show gamut triangular surface */
tp = s->tris;
FOR_ALL_ITEMS(gtri, tp) {
- fprintf(wrl,"%d, %d, %d, -1\n", tp->v[0]->tn, tp->v[1]->tn, tp->v[2]->tn);
+ int ix[3];
+ ix[0] = tp->v[0]->tn;
+ ix[1] = tp->v[1]->tn;
+ ix[2] = tp->v[2]->tn;
+ wrl->add_triangle(wrl, 0, ix);
} END_FOR_ALL_ITEMS(tp);
#endif /* SHOW_BUCKETS */
- fprintf(wrl," ]\n");
- fprintf(wrl,"\n");
- fprintf(wrl," colorPerVertex TRUE\n");
- fprintf(wrl," color Color {\n");
- fprintf(wrl," color [ # RGB colors of each vertex\n");
-
- /* Spit out the colors for each vertex */
- for (i = 0; i < s->nv; i++) {
+ {
double rgb[3];
-#ifdef SHOW_BUCKETS /* Show vertex buckets as surface */
- if (!(s->verts[i]->f & GVERT_SET))
-#else
- if (!(s->verts[i]->f & GVERT_TRI))
-#endif
- continue;
#ifdef COLORED_VRML
- gamut_Lab2RGB(rgb, s->verts[i]->p);
+ rgb[0] = -1.0;
#else
rgb[0] = rgb[1] = rgb[2] = 1.0;
#endif
- fprintf(wrl,"%f %f %f,\n", rgb[0], rgb[1], rgb[2]);
+
#ifdef SHOW_BUCKETS /* Show vertex buckets as surface */
- fprintf(wrl,"%f %f %f,\n", rgb[0], rgb[1], rgb[2]);
- fprintf(wrl,"%f %f %f,\n", rgb[0], rgb[1], rgb[2]);
- fprintf(wrl,"%f %f %f,\n", rgb[0], rgb[1], rgb[2]);
+ wrl->make_quads(wrl, 0, 0.0, rgb);
+#else /* !SHOW_BUCKETS */
+ wrl->make_triangles(wrl, 0, 0.0, rgb);
#endif /* SHOW_BUCKETS */
}
- fprintf(wrl," ] \n");
- fprintf(wrl," }\n");
- fprintf(wrl," }\n");
- fprintf(wrl," appearance Appearance { \n");
- fprintf(wrl," material Material {\n");
- fprintf(wrl," transparency 0.0\n");
- fprintf(wrl," ambientIntensity 0.3\n");
- fprintf(wrl," shininess 0.5\n");
- fprintf(wrl," }\n");
- fprintf(wrl," }\n");
- fprintf(wrl," } # end Shape\n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
if (s->gawbset && doaxes) {
+ double rgb[3] = { 0.9, 0.9, 0.9 };
/* Show the gamut white and black points */
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation %f %f %f\n",s->ga_wp[1]-s->cent[1], s->ga_wp[2]-s->cent[2], s->ga_wp[0]-s->cent[0]);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry Sphere { radius 2.0 }\n");
- fprintf(wrl," appearance Appearance { material Material { diffuseColor 0.9 0.9 0.9 } }\n");
- fprintf(wrl," } \n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation %f %f %f\n",s->ga_bp[1]-s->cent[1], s->ga_bp[2]-s->cent[2], s->ga_bp[0]-s->cent[0]);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry Sphere { radius 2.0 }\n");
- fprintf(wrl," appearance Appearance { material Material { diffuseColor 0.9 0.9 0.9 } }\n");
- fprintf(wrl," } \n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
+ wrl->add_marker(wrl, s->ga_wp, rgb, 2.0);
+ wrl->add_marker(wrl, s->ga_bp, rgb, 2.0);
}
if (docusps && s->cu_inited != 0) {
@@ -6075,30 +5963,17 @@ void *cntx
{ 1.0, 0.1, 1.0 } /* Magenta */
};
- for (i = 0; i < 6; i++) {
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation %f %f %f\n",s->cusps[i][1]-s->cent[1], s->cusps[i][2]-s->cent[2], s->cusps[i][0]-s->cent[0]);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry Sphere { radius 2.0 }\n");
- fprintf(wrl," appearance Appearance { material Material { diffuseColor %f %f %f } }\n", ccolors[i][0],ccolors[i][1],ccolors[i][2]);
- fprintf(wrl," } \n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- }
+ for (i = 0; i < 6; i++)
+ wrl->add_marker(wrl, s->cusps[i], ccolors[i], 2.0);
}
#ifdef TEST_LOOKUP
{
int i, j;
double in[3], out[3];
+ double rgb[3] = { 1.0, 1.0, 1.0 };
- fprintf(wrl,"\n");
- fprintf(wrl,"Shape {\n");
- fprintf(wrl," geometry PointSet { \n");
- fprintf(wrl," coord Coordinate { \n");
- fprintf(wrl," point [\n");
+ wrl->start_line_set(wrl, 0);
for (i = 0; i < 10; i++) {
double ss;
@@ -6112,13 +5987,12 @@ void *cntx
out[0] = (out[0] - s->cent[0]) * 1.01 + s->cent[0];
out[1] = (out[1] - s->cent[1]) * 1.01 + s->cent[1];
out[2] = (out[2] - s->cent[2]) * 1.01 + s->cent[2];
- fprintf(wrl,"%f %f %f,\n",out[1]-s->cent[1], out[2]-s->cent[2], out[0]-s->cent[0]);
+
+ wrl->add_col_vertex(wrl, 0, out, rgb);
}
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"} # end shape\n");
+ /* Convert them to a point set */
+ wrl->make_points(wrl, 0);
}
#endif /* TEST_LOOKUP */
@@ -6128,11 +6002,7 @@ void *cntx
int i, j;
double in[3], out[3];
- fprintf(wrl,"\n");
- fprintf(wrl,"Shape {\n");
- fprintf(wrl," geometry IndexedLineSet { \n");
- fprintf(wrl," coord Coordinate { \n");
- fprintf(wrl," point [\n");
+ wrl->start_line_set(wrl, 0);
for (i = 0; i < NTPTS; i++) {
double ss;
@@ -6161,37 +6031,23 @@ void *cntx
s->nearest(s, out, in); /* Nearest point on gamut surface */
- fprintf(wrl,"%f %f %f,\n",in[1]-s->cent[1], in[2]-s->cent[2], in[0]-s->cent[0]);
- fprintf(wrl,"%f %f %f,\n",out[1]-s->cent[1], out[2]-s->cent[2], out[0]-s->cent[0]);
+ wrl->add_vertex(wrl, 0, in);
+ wrl->add_vertex(wrl, 0, out);
}
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl," coordIndex [\n");
-
- for (i = 0; i < NTPTS; i++) {
- fprintf(wrl,"%d, %d, -1,\n", i * 2, i * 2 + 1);
- }
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"} # end shape\n");
-
+ wrl->make_lines(wrl, 0, 2);
}
#endif /* TEST_NEAREST */
- fprintf(wrl,"\n");
- fprintf(wrl," ] # end of children for world\n");
- fprintf(wrl,"}\n");
-
- if (fclose(wrl) != 0) {
- fprintf(stderr,"Error closing output file '%s'\n",filename);
+ if (wrl->flush(wrl)) {
+ fprintf(stderr,"Error closing output file '%s%s'\n",filename,vrml_ext());
return 2;
}
+ wrl->del(wrl);
return 0;
}
-
/* ----------------------------------- */
/* Write to a CGATS .gam file */
/* Return non-zero on error */
@@ -6277,7 +6133,7 @@ char *filename
if (!(s->verts[i]->f & GVERT_TRI))
continue;
gam->add_set(gam, 0, s->verts[i]->tn,
- s->verts[i]->p[0], s->verts[i]->p[1], s->verts[i]->p[2]);
+ s->verts[i]->p[0], s->verts[i]->p[1], s->verts[i]->p[2]);
}
gam->add_table(gam, tt_other, 0); /* Start the second table */
@@ -6370,12 +6226,12 @@ char *filename
if (cw >= 0 && cb >= 0) {
int ok = 1;
if (sscanf(gam->t[0].kdata[cw], "%lf %lf %lf",
- &s->cs_wp[0], &s->cs_wp[1], &s->cs_wp[2]) != 3) {
+ &s->cs_wp[0], &s->cs_wp[1], &s->cs_wp[2]) != 3) {
ok = 0;
}
if (sscanf(gam->t[0].kdata[cb], "%lf %lf %lf",
- &s->cs_bp[0], &s->cs_bp[1], &s->cs_bp[2]) != 3) {
+ &s->cs_bp[0], &s->cs_bp[1], &s->cs_bp[2]) != 3) {
ok = 0;
}
@@ -6390,12 +6246,12 @@ char *filename
if (gw >= 0 && gb >= 0) {
int ok = 1;
if (sscanf(gam->t[0].kdata[gw], "%lf %lf %lf",
- &s->ga_wp[0], &s->ga_wp[1], &s->ga_wp[2]) != 3) {
+ &s->ga_wp[0], &s->ga_wp[1], &s->ga_wp[2]) != 3) {
ok = 0;
}
if (sscanf(gam->t[0].kdata[gb], "%lf %lf %lf",
- &s->ga_bp[0], &s->ga_bp[1], &s->ga_bp[2]) != 3) {
+ &s->ga_bp[0], &s->ga_bp[1], &s->ga_bp[2]) != 3) {
ok = 0;
}
@@ -6416,7 +6272,7 @@ char *filename
break;
if (sscanf(gam->t[0].kdata[kk], "%lf %lf %lf",
- &s->cusps[i][0], &s->cusps[i][1], &s->cusps[i][2]) != 3) {
+ &s->cusps[i][0], &s->cusps[i][1], &s->cusps[i][2]) != 3) {
break;
}
}
@@ -6577,7 +6433,7 @@ char *filename
|| tp2->e[em] != NULL) {
fprintf(stderr,".gam file triangle data is not consistent\n");
fprintf(stderr,"tp1->e[%d] = 0x%p, tp2->e[%d]= 0x%p\n",en,
- (void *)tp->e[en],em,(void *)tp2->e[em]);
+ (void *)tp->e[en],em,(void *)tp2->e[em]);
return 1;
}
@@ -6621,7 +6477,6 @@ double in[3] /* Lab in */
double L, a, b; /* Lab values */
double R, g, t; /* Radial value */
double c; /* Chromatic length */
-
L = in[0] - s->cent[0]; /* Offset value */
a = in[1] - s->cent[1];
@@ -6685,76 +6540,9 @@ double in[3] /* Radius, longitude, lattitude in */
/* -------------------------------------------------- */
-/* Convert a gamut Lab value to an RGB value for display purposes */
-void
-gamut_Lab2RGB(double *out, double *in) {
- double L = in[0], a = in[1], b = in[2];
- double x,y,z,fx,fy,fz;
- double R, G, B;
-
- /* Scale so that black is visible */
- L = L * (100 - 40.0)/100.0 + 40.0;
-
- /* First convert to XYZ using D50 white point */
- if (L > 8.0) {
- fy = (L + 16.0)/116.0;
- y = pow(fy,3.0);
- } else {
- y = L/903.2963058;
- fy = 7.787036979 * y + 16.0/116.0;
- }
-
- fx = a/500.0 + fy;
- if (fx > 24.0/116.0)
- x = pow(fx,3.0);
- else
- x = (fx - 16.0/116.0)/7.787036979;
-
- fz = fy - b/200.0;
- if (fz > 24.0/116.0)
- z = pow(fz,3.0);
- else
- z = (fz - 16.0/116.0)/7.787036979;
-
- x *= 0.9642; /* Multiply by white point, D50 */
- y *= 1.0;
- z *= 0.8249;
-
- /* Now convert to sRGB values */
- R = x * 3.2410 + y * -1.5374 + z * -0.4986;
- G = x * -0.9692 + y * 1.8760 + z * 0.0416;
- B = x * 0.0556 + y * -0.2040 + z * 1.0570;
-
- if (R < 0.0)
- R = 0.0;
- else if (R > 1.0)
- R = 1.0;
-
- if (G < 0.0)
- G = 0.0;
- else if (G > 1.0)
- G = 1.0;
-
- if (B < 0.0)
- B = 0.0;
- else if (B > 1.0)
- B = 1.0;
-
- R = pow(R, 1.0/2.2);
- G = pow(G, 1.0/2.2);
- B = pow(B, 1.0/2.2);
-
- out[0] = R;
- out[1] = G;
- out[2] = B;
-}
+#if defined(DEBUG_TRIANG) || defined(DEBUG_TRIANG_VRML)
-
-/* -------------------------------------------------- */
-
-#ifdef DEBUG_TRIANG
-
-/* Write a surface contrsuction diagnostic VRML .wrl file */
+/* Write a surface construction diagnostic .wrl/.x3d/.x3dom file */
static int write_diag_vrml(
gamut *s,
double vv[3], /* Vertex being added */
@@ -6763,54 +6551,24 @@ tidxs *hixs, /* verticy indexes of hit triangles */
gtri *hl /* Edge hit list (may be NULL) */
) {
char *filename;
+ int doaxes = 0;
int i, j;
gtri *tp; /* Triangle pointer */
- FILE *wrl;
+ vrml *wrl;
if (hl)
- filename = "diag1.wrl"; /* Triangles hit */
+ filename = "diag1"); /* Triangles hit */
else
- filename = "diag2.wrl"; /* Triangles formed */
+ filename = "diag2"); /* Triangles formed */
- if ((wrl = fopen(filename,"w")) == NULL) {
- fprintf(stderr,"Error opening output file '%s'\n",filename);
+ if ((wrl = new_vrml_vdist(filename, doaxes, vrml_lab, 200.0)) == NULL) {
+ fprintf(stderr,"Error creating vrml object '%s%s'\n",filename,vrml_ext());
return 2;
}
- /* Spit out a VRML 2 Object surface of gamut */
-
- fprintf(wrl,"#VRML V2.0 utf8\n");
- fprintf(wrl,"\n");
- fprintf(wrl,"# Created by the Argyll CMS\n");
- fprintf(wrl,"Transform {\n");
- fprintf(wrl,"children [\n");
- fprintf(wrl," NavigationInfo {\n");
- fprintf(wrl," type \"EXAMINE\" # It's an object we examine\n");
- fprintf(wrl," } # We'll add our own light\n");
- fprintf(wrl,"\n");
- fprintf(wrl," DirectionalLight {\n");
- fprintf(wrl," direction 0 0 -1 # Light illuminating the scene\n");
- fprintf(wrl," direction 0 -1 0 # Light illuminating the scene\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- fprintf(wrl," Viewpoint {\n");
- fprintf(wrl," position 0 0 200 # Position we view from\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
-
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation 0 0 0\n");
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry IndexedFaceSet {\n");
- fprintf(wrl," ccw FALSE\n");
- fprintf(wrl," convex TRUE\n");
- fprintf(wrl,"\n");
- fprintf(wrl," coord Coordinate { \n");
- fprintf(wrl," point [ # Verticy coordinates\n");
+ wrl->start_line_set(wrl, 0);
/* Spit out the vertex values, in order. */
- /* Note that a->x, b->y, L->z */
for (i = 0; i < s->nv; i++) {
double out[3];
@@ -6819,284 +6577,140 @@ gtri *hl /* Edge hit list (may be NULL) */
out[1] = s->verts[i]->ch[1];
out[2] = s->verts[i]->ch[2];
- fprintf(wrl,"%f %f %f,\n",out[1], out[2], out[0]);
+ wrl->add_vertex(wrl, 0, out);
}
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- fprintf(wrl," coordIndex [ # Indexes of poligon Verticies \n");
+ /* Create triangles from verticies and set tri color */
tp = s->tris;
FOR_ALL_ITEMS(gtri, tp) {
- fprintf(wrl,"%d, %d, %d, -1\n", tp->v[0]->n, tp->v[1]->n, tp->v[2]->n);
+ int ix[3];
+ double rgb[3] = { 0.7, 0.7, 0.7 };
+
+ ix[0] = tp->v[0]->n;
+ ix[1] = tp->v[1]->n;
+ ix[2] = tp->v[2]->n;
+
+ wrl->add_col_triangle(wrl, 0, ix, rgb);
} END_FOR_ALL_ITEMS(tp);
for (i = 0; i < nh; i++) {
- fprintf(wrl,"%d, %d, %d, -1\n", hixs[i].tix[0], hixs[i].tix[1], hixs[i].tix[2]);
+ double rgb[3] = { 0.7, 0.7, 0.7 };
+
+ if (hixs[i].type == 0) {
+ rgb[0] = 0.4; rgb[1] = 1.0; rgb[2] = 0.4; /* Green for hit */
+ } else if (hixs[i].type == 1) {
+ rgb[0] = 0.4; rgb[1] = 0.4; rgb[2] = 1.0; /* Blue for extra */
+ } else {
+ rgb[0] = 0.8; rgb[1] = 0.8; rgb[2] = 0.2; /* Yellow for new */
+ }
+
+ wrl->add_col_triangle(wrl, 0, hixs[i].tix, rgb);
}
- fprintf(wrl," ]\n");
- fprintf(wrl,"\n");
- fprintf(wrl," colorPerVertex FALSE\n");
- fprintf(wrl," color Color {\n");
- fprintf(wrl," color [ # RGB colors of each vertex\n");
+ wrl->make_triangles_vc(wrl, 0, 0.0);
- /* Spit out the colors for each face */
- tp = s->tris;
- FOR_ALL_ITEMS(gtri, tp) {
- fprintf(wrl,"%f %f %f,\n", 0.7, 0.7, 0.7);
- } END_FOR_ALL_ITEMS(tp);
- for (i = 0; i < nh; i++) {
- if (hixs[i].type == 0)
- fprintf(wrl,"%f %f %f,\n", 0.4, 1.0, 0.4); /* Green for hit */
- else if (hixs[i].type == 1)
- fprintf(wrl,"%f %f %f,\n", 0.4, 0.4, 1.0); /* Blue for extra */
- else
- fprintf(wrl,"%f %f %f,\n", 0.8, 0.8, 0.2); /* Yellow for new */
- }
- fprintf(wrl," ] \n");
- fprintf(wrl," }\n");
- fprintf(wrl," } # end IndexedFaceSet\n");
-
- fprintf(wrl," appearance Appearance { \n");
- fprintf(wrl," material Material {\n");
- fprintf(wrl," transparency 0.0\n");
- fprintf(wrl," ambientIntensity 0.3\n");
- fprintf(wrl," shininess 0.5\n");
- fprintf(wrl," }\n");
- fprintf(wrl," }\n");
- fprintf(wrl," } # end Shape\n");
- fprintf(wrl," ]\n");
- fprintf(wrl," } # end of transform\n");
+ {
+ double pos[3], rgb[3];
- /* center of gamut */
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation %f %f %f\n",0.0, 0.0, 0.0);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry Sphere { radius 1.5 }\n");
- fprintf(wrl," appearance Appearance { material Material { diffuseColor %f %f %f } }\n", 1.0, 1.0, 0.0);
- fprintf(wrl," } \n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
-
- /* vertex being added */
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation %f %f %f\n",vv[1], vv[2], vv[0]);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry Sphere { radius 1.5 }\n");
- fprintf(wrl," appearance Appearance { material Material { diffuseColor %f %f %f } }\n", 1.0, 0.0, 0.0);
- fprintf(wrl," } \n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
+ /* center of gamut */
+ pos[0] = 0.0; pos[1] = 0.0, pos[2] = 0.0;
+ rgb[0] = 1.0; rgb[1] = 1.0, rgb[2] = 0.0; /* Yellow */
+ wrl->add_marker(wrl, pos, rgb, 1.5);
+ /* vertex being added */
+ rgb[0] = 1.0; rgb[1] = 0.0, rgb[2] = 0.0; /* Red */
+ wrl->add_marker(wrl, vv, rgb, 1.5);
+ }
/* Verticies for Polygon edges, marked by directional cones */
if (hl != NULL) {
- double base[3] = { 0.0, 0.0, 1.0 }; /* Default orientation of cone is b axis */
tp = hl;
FOR_ALL_ITEMS(gtri, tp) {
- double len;
- double loc[3];
- double vec[3];
- double axis[3]; /* Axis to rotate around */
- double rot; /* In radians */
-
-//printf("~1 edge vert %d to %d\n",tp->v[0]->n, tp->v[1]->n);
-//printf("~1 edge %f %f %f to %f %f %f\n",
-//tp->v[0]->ch[0], tp->v[0]->ch[1], tp->v[0]->ch[2],
-//tp->v[1]->ch[0], tp->v[1]->ch[1], tp->v[1]->ch[2]);
-
- icmAdd3(loc, tp->v[1]->ch, tp->v[0]->ch);
- icmScale3(loc, loc, 0.5);
- icmSub3(vec, tp->v[1]->ch, tp->v[0]->ch);
- len = icmNorm3(vec);
-
- if (len < 1.0)
- len = 1.0;
-
- icmNormalize3(base, base, 1.0);
- icmNormalize3(vec, vec, 1.0);
- icmCross3(axis, base, vec);
- rot = icmDot3(base, vec);
-//printf("~1 Axis = %f %f %f\n",axis[0],axis[1],axis[2]);
- if (icmNorm3sq(axis) < 1e-10) { /* 0 or 180 degrees */
- double base2[3];
- int mxi = 0;
- base2[0] = vec[1]; /* Comute vector in a different direction */
- base2[1] = vec[2];
- base2[2] = vec[0];
- for (j = 1; j < 3; j++) {
- if (fabs(base2[j]) > fabs(base2[mxi]))
- mxi = j;
- }
- base2[mxi] = -base2[mxi];
-
- icmCross3(axis, base2, vec);
- if (icmNorm3sq(axis) < 1e-10) { /* 0 or 180 degrees */
- error("VRML rotate axis still too small");
- }
- if (rot < 0.0)
- rot = 3.1415926;
- else
- rot = 0.0;
- } else {
- rot = acos(rot);
-//printf("~1 rotation %f\n",rot);
- }
-
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," rotation %f %f %f %f\n",axis[1], axis[2], axis[0], rot);
- fprintf(wrl," translation %f %f %f\n",loc[1], loc[2], loc[0]);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry Cone { bottomRadius 0.5 height %f }\n",len);
- fprintf(wrl," appearance Appearance { material Material { diffuseColor 0.7 0.0 1.0 } }\n");
- fprintf(wrl," } \n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
+ double rgb[3] = { 0.7, 0.0, 1.0 };
+ wrl->add_cone(wrl, tp->v[0]->ch, tp->v[1]->ch, rgb, 0.5);
} END_FOR_ALL_ITEMS(tp);
}
- fprintf(wrl,"\n");
- fprintf(wrl," ] # end of children for world\n");
- fprintf(wrl,"}\n");
-
- if (fclose(wrl) != 0) {
- fprintf(stderr,"Error closing output file '%s'\n",filename);
+ if (wrl->flush(wrl) != 0) {
+ fprintf(stderr,"Error closing output file '%s%s'\n",filename,vrml_ext());
return 2;
}
return 0;
}
-#endif /* DEBUG_TRIANG */
+#endif /* DEBUG_TRIANG_VRML */
#ifdef DEBUG_SPLIT_VRML
-/* Write a triangle split diagnostic VRML .wrl file */
+/* Write a triangle split diagnostic .wrl/.x3d/.x3dom file */
static int write_split_diag_vrml(
gamut *s,
gtri **list, /* Triangle list */
int llen /* Number of triangles in the list */
) {
- char *filename;
int i, j;
- FILE *wrl;
-
- filename = "diag3.wrl"; /* Triangles split */
+ int doaxes = 0;
+ vrml *wrl;
- if ((wrl = fopen(filename,"w")) == NULL) {
- fprintf(stderr,"Error opening output file '%s'\n",filename);
+ if ((wrl = new_vrml("diag3", doaxes, vrml_lab)) == NULL) {
+ fprintf(stderr,"Error creating %s object '%s%s'\n",vrml_format(),filename,vrml_ext());
return 2;
}
- /* Spit out a VRML 2 Object surface of gamut */
-
- fprintf(wrl,"#VRML V2.0 utf8\n");
- fprintf(wrl,"\n");
- fprintf(wrl,"# Created by the Argyll CMS\n");
- fprintf(wrl,"Transform {\n");
- fprintf(wrl,"children [\n");
- fprintf(wrl," NavigationInfo {\n");
- fprintf(wrl," type \"EXAMINE\" # It's an object we examine\n");
- fprintf(wrl," } # We'll add our own light\n");
- fprintf(wrl,"\n");
- fprintf(wrl," DirectionalLight {\n");
- fprintf(wrl," ambientIntensity 0.3 # Ambient light illuminating the scene\n");
- fprintf(wrl," direction 0 0 -1 # Light illuminating the scene\n");
- fprintf(wrl," direction 0 -1 0 # Light illuminating the scene\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- fprintf(wrl," Viewpoint {\n");
- fprintf(wrl," position 0 0 5 # Position we view from\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
-
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation 0 0 0\n");
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry IndexedFaceSet {\n");
- fprintf(wrl," ccw FALSE\n");
- fprintf(wrl," convex TRUE\n");
- fprintf(wrl," solid FALSE\n");
- fprintf(wrl,"\n");
- fprintf(wrl," coord Coordinate { \n");
- fprintf(wrl," point [ # Verticy coordinates\n");
+ wrl->start_line_set(wrl, 0);
/* Spit out the vertex values, in order. */
for (i = 0; i < llen; i++) {
- fprintf(wrl,"%f %f %f,\n",list[i]->v[0]->sp[0], list[i]->v[0]->sp[1], list[i]->v[0]->sp[2]);
- fprintf(wrl,"%f %f %f,\n",list[i]->v[1]->sp[0], list[i]->v[1]->sp[1], list[i]->v[1]->sp[2]);
- fprintf(wrl,"%f %f %f,\n",list[i]->v[2]->sp[0], list[i]->v[2]->sp[1], list[i]->v[2]->sp[2]);
- }
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- fprintf(wrl," coordIndex [ # Indexes of poligon Verticies \n");
+ double pos[3];
- for (i = 0; i < llen; i++) {
- fprintf(wrl,"%d, %d, %d, -1\n", i * 3 + 0, i * 3 + 1, i * 3 + 2);
+ for (j = 0; j < 3; j++) {
+
+ pos[0] = 100.0 * list[i]->v[j]->sp[0];
+ pos[1] = 100.0 * list[i]->v[j]->sp[1];
+ pos[2] = 100.0 * list[i]->v[j]->sp[2];
+
+ wrl->add_vertex(wrl, 0, pos);
+ }
}
- fprintf(wrl," ]\n");
- fprintf(wrl,"\n");
- fprintf(wrl," colorPerVertex FALSE\n");
- fprintf(wrl," color Color {\n");
- fprintf(wrl," color [ # RGB colors of each vertex\n");
- /* Spit out the colors for each face */
+ /* Triangle faces and colors */
for (i = 0; i < llen; i++) {
+ int ix[3];
+ double rgb[3];
+
+ ix[0] = i * 3 + 0;
+ ix[1] = i * 3 + 1;
+ ix[2] = i * 3 + 2;
+
if (list[i]->bsort == 1) { /* Positive */
- fprintf(wrl,"%f %f %f,\n", 1.0, 0.3, 0.3); /* Red */
+ rgb[0]= 1.0; rgb[1] = 0.3; rgb[2] = 0.3; /* Red */
} else if (list[i]->bsort == 2) { /* Negative */
- fprintf(wrl,"%f %f %f,\n", 0.3, 1.0, 0.3); /* Green */
+ rgb[0]= 0.3; rgb[1] = 1.0; rgb[2] = 0.3; /* Green */
} else if (list[i]->bsort == 3) { /* Both */
- fprintf(wrl,"%f %f %f,\n", 1.0, 1.0, 0.3); /* Yellow */
+ rgb[0]= 1.0; rgb[1] = 1.0; rgb[2] = 0.3; /* Yellow */
} else { /* Neither */
- fprintf(wrl,"%f %f %f,\n", 0.3, 0.3, 1.0); /* Blue */
- }
+ rgb[0]= 0.3; rgb[1] = 0.3; rgb[2] = 1.0; /* Blue */
+ }
+ wrl->add_col_triangle(wrl, 0, ix, rgb);
}
- fprintf(wrl," ] \n");
- fprintf(wrl," }\n");
- fprintf(wrl," } # end IndexedFaceSet\n");
-
- fprintf(wrl," appearance Appearance { \n");
- fprintf(wrl," material Material {\n");
- fprintf(wrl," transparency 0.0\n");
- fprintf(wrl," ambientIntensity 0.3\n");
- fprintf(wrl," shininess 0.5\n");
- fprintf(wrl," }\n");
- fprintf(wrl," }\n");
- fprintf(wrl," } # end Shape\n");
- fprintf(wrl," ]\n");
- fprintf(wrl," } # end of transform\n");
+
+ wrl->make_triangles_vc(wrl, 0, 0.0);
/* center of gamut */
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation %f %f %f\n",0.0, 0.0, 0.0);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry Sphere { radius 0.05 }\n");
- fprintf(wrl," appearance Appearance { material Material { diffuseColor %f %f %f } }\n", 1.0, 1.0, 0.0);
- fprintf(wrl," } \n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
-
- fprintf(wrl,"\n");
- fprintf(wrl," ] # end of children for world\n");
- fprintf(wrl,"}\n");
-
- if (fclose(wrl) != 0) {
- fprintf(stderr,"Error closing output file '%s'\n",filename);
+ {
+ double pos[3] = { 0.0, 0.0, 0.0 };
+ double rgb[3] = { 1.0, 1.0, 0.0 }; /* Yellow */
+
+ wrl->add_marker(wrl, pos, rgb, 5.0);
+ }
+
+ if (wrl->flush(wrl) != 0) {
+ fprintf(stderr,"Error closing output file '%s%s'\n",filename,vrml_ext());
return 2;
}
+ wrl->del(wrl);
return 0;
}
diff --git a/gamut/gamut.h b/gamut/gamut.h
index 8f4645c..467852f 100644
--- a/gamut/gamut.h
+++ b/gamut/gamut.h
@@ -344,8 +344,9 @@ struct _gamut {
int (*vector_isect)(struct _gamut *s, double *p1, double *p2, double *min, double *max,
double *mint, double *maxt,
gtri **mntri, gtri **mxtri);
- /* Compute the intersection of the vector p1->p2 with */
- /* the gamut surface. min is the intersection in the p1 direction, */
+ /* Compute the intersection of the (extended to infinity) vector */
+ /* p1->p2 with the gamut surface. */
+ /* min is the intersection in the p1 direction, */
/* max is intersection in the p2 direction. mint and maxt are */
/* the parameter values at the two intersection points, a value of 0 */
/* being at p1 and 1 being at p2. mintri and maxtri return the */
@@ -384,11 +385,11 @@ struct _gamut {
/* Following return nz on error: */
int (*write_vrml)(struct _gamut *s, char *filename,
- int doaxes, int docusps); /* Write to a VRML .wrl file */
+ int doaxes, int docusps); /* Write to a VRML .wrl/.x3d file */
int (*write_gam)(struct _gamut *s, char *filename); /* Write to a CGATS .gam file */
int (*read_gam)(struct _gamut *s, char *filename); /* Read from a CGATS .gam file */
- int (*write_trans_vrml)(struct _gamut *s, char *filename, /* Write transformed VRML .wrl */
+ int (*write_trans_vrml)(struct _gamut *s, char *filename, /* Write transformed VRML/X3D .wrl */
int doaxes, int docusps, void (*transform)(void *cntx, double out[3], double in[3]), /* with xform */
void *cntx);
diff --git a/gamut/maptest.c b/gamut/maptest.c
index 5fe5c42..3a33453 100644
--- a/gamut/maptest.c
+++ b/gamut/maptest.c
@@ -32,6 +32,8 @@
#include "gamut.h"
#include "rspl.h"
#include "gammap.h"
+#include "vrml.h"
+#include "ui.h"
void usage(void) {
fprintf(stderr,"Map bteween two gamuts, Version %s\n",ARGYLL_VERSION_STR);
@@ -55,12 +57,15 @@ main(int argc, char *argv[]) {
int verb = 0;
gammap *map; /* Regular split gamut mapping */
icxGMappingIntent gmi;
+ char gammapwrl[30] = "gammap"; /* Diagnostic file name */
gamut *gin, *gout; /* Input and Output gamuts */
gamut *gimg = NULL; /* Optional image gamut */
error_program = argv[0];
+ strcat(gammapwrl, vrml_ext());
+
if (argc < 3)
usage();
@@ -203,7 +208,7 @@ main(int argc, char *argv[]) {
17, /* rspl resolution of 17 */
NULL, /* No input range override */
NULL,
- "gammap.wrl" /* Diagnostic plot */
+ gammapwrl /* Diagnostic plot */
);
if (map == NULL) {
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);
diff --git a/gamut/nearsmth.h b/gamut/nearsmth.h
index 6e94969..f826357 100644
--- a/gamut/nearsmth.h
+++ b/gamut/nearsmth.h
@@ -91,10 +91,12 @@ typedef struct {
/* Cusp alignment control */
struct {
iweight w; /* Component alignment weights, 0 - 1 */
+ double tw; /* Alignment twist power, 0 = linear, 1 = curve, 2+ late curve */
+ /* Use > 0 to make cusp alignment only affect surface colors. */
double cx; /* Chroma expansion, 1 = none, > 1 = more */
} c;
- /* Radial weighting */
+ /* Radial weighting (This seems to be not working at the moment ?) */
/* Weight to give to minimizing delta E to source mapped radially */
struct {
double o; /* Overall Radial weight */
@@ -102,7 +104,7 @@ typedef struct {
double l; /* l dominance vs, c, 0 - 1 */
} l;
- /* Absolute error weighting */
+ /* Absolute error weighting. */
/* Weight given to minimizing delta E to destination closest point */
struct {
double o; /* Overall Absolute weight */
@@ -166,7 +168,7 @@ struct _nearsmth {
/* Public: */
int gflag; /* Gamut direction flag. 0 = not determinable, 1 = comp., 2 = exp. */
int vflag; /* Vector direction flag. 0 = not determinable, 1 = comp., 2 = exp. */
- /* sv2 & dv2 are valid if vflag != 0 */
+ /* sv2, dv2, sd3 etc. are valid if vflag != 0 */
/* Gamut surface mapping guide point */
double sv[3]; /* Source value (input, cusp aligned during fwd optimization) */
@@ -179,9 +181,12 @@ struct _nearsmth {
/* Gamut sub-surface mapping guide point (knee shape controlled by gamcknf & gamxknf) */
double sv2[3]; /* Sub-surface source value */
- double dv2[3]; /* Sub-surface destination value */
+ double dv2[3]; /* Sub-surface knee'd adjusted destination value */
double div2[3]; /* gam[cx]pf moderated dv2[] value */
- double w2; /* Sub-surface weight */
+ double w2; /* Sub-surface weight (fixed in nearsmth) */
+
+ double sd3[3]; /* Deep sub-surface source & destination value */
+ double w3; /* Deep sub-surface weight */
/* Diagnostic points */
double csv[3]; /* Non-cusp mapped source value */
@@ -215,6 +220,8 @@ struct _nearsmth {
double dcratio; /* Depth compression ratio */
double dxratio; /* Depth expansion ratio */
+ int mapres; /* Target grid res for 3D RSPL */
+
int debug;
double dbgv[4]; /* Error components va, vr, vl, vd on last itteration */
diff --git a/gamut/smthtest.c b/gamut/smthtest.c
index 24fdfef..c9214d3 100644
--- a/gamut/smthtest.c
+++ b/gamut/smthtest.c
@@ -35,6 +35,8 @@
#include "rspl.h"
#include "gamut.h"
#include "nearsmth.h"
+#include "vrml.h"
+#include "ui.h"
double m21po[3] = { 2.0, 1.0, 2.0 }; /* Many to 1 filter mixing power LCh (theoretically 2) */
@@ -44,8 +46,8 @@ gammapweights weights[] = {
gmm_default, /* Non hue specific defaults */
{ /* Cusp alignment control */
{
- 0.0, /* Cusp luminance alignment weighting 0 = none, 1 = full */
- 0.0, /* Cusp chroma alignment weighting 0 = none, 1 = full */
+ 0.1, /* Cusp luminance alignment weighting 0 = none, 1 = full */
+ 0.1, /* Cusp chroma alignment weighting 0 = none, 1 = full */
0.2 /* Cusp hue alignment weighting 0 = none, 1 = full */
},
1.00 /* Chroma expansion 1 = none */
@@ -91,12 +93,6 @@ void usage(void) {
exit(1);
}
-FILE *start_vrml(char *name, int doaxes);
-void start_line_set(FILE *wrl);
-void add_vertex(FILE *wrl, double pp[3]);
-void make_lines(FILE *wrl, int ppset);
-void end_vrml(FILE *wrl);
-
int
main(int argc, char *argv[]) {
int fa,nfa; /* argument we're looking at */
@@ -112,7 +108,8 @@ main(int argc, char *argv[]) {
gamut *gin, *gout; /* Input and Output gamuts */
nearsmth *nsm; /* Returned list of near smooth points */
int nnsm; /* Number of near smoothed points */
- FILE *wrl; /* VRML output file */
+ int doaxes = 1;
+ vrml *wrl; /* VRML/X3D output file */
gammapweights xweights[14];
@@ -218,22 +215,25 @@ main(int argc, char *argv[]) {
error("Creating smoothed near points failed");
/* Output the src to smoothed near point vectors */
- if ((xl = strrchr(diag_name, '.')) == NULL) { /* Add .wrl extention if there isn't one */
+ if ((xl = strrchr(diag_name, '.')) == NULL) /* Clear extension */
xl = diag_name + strlen(diag_name);
- strcpy(xl,".wrl");
+ xl[0] = '\000';
+
+ if ((wrl = new_vrml(diag_name, doaxes, vrml_lab)) != 0) {
+ error("new_vrml failed for '%s%s'",diag_name,vrml_ext());
}
- wrl = start_vrml(diag_name, 1);
- start_line_set(wrl);
+ wrl->start_line_set(wrl, 0);
for (i = 0; i < nnsm; i++) {
- add_vertex(wrl, nsm[i].sv); /* Source gamut point */
- add_vertex(wrl, nsm[i].dv); /* Smoother destination value */
+ wrl->add_vertex(wrl, 0, nsm[i].sv); /* Source gamut point */
+ wrl->add_vertex(wrl, 0, nsm[i].dv); /* Smoother destination value */
// add_vertex(wrl, nsm[i].drv); /* Radial points */
}
- make_lines(wrl, 2);
- end_vrml(wrl);
+ wrl->make_lines(wrl, 0, 2);
+
+ wrl->del(wrl); /* Write file */
/* Clean up */
free_nearsmth(nsm, nnsm);
@@ -244,217 +244,4 @@ main(int argc, char *argv[]) {
return 0;
}
-/* ------------------------------------------------ */
-/* Some simple functions to do basic VRML work */
-
-#ifndef GAMUT_LCENT
-#define GAMUT_LCENT 50.0
-#endif
-static int npoints = 0;
-static int paloc = 0;
-static struct { double pp[3]; } *pary;
-
-static void Lab2RGB(double *out, double *in);
-
-FILE *start_vrml(char *name, int doaxes) {
- FILE *wrl;
- struct {
- double x, y, z;
- double wx, wy, wz;
- double r, g, b;
- } axes[5] = {
- { 0, 0, 50-GAMUT_LCENT, 2, 2, 100, .7, .7, .7 }, /* L axis */
- { 50, 0, 0-GAMUT_LCENT, 100, 2, 2, 1, 0, 0 }, /* +a (red) axis */
- { 0, -50, 0-GAMUT_LCENT, 2, 100, 2, 0, 0, 1 }, /* -b (blue) axis */
- { -50, 0, 0-GAMUT_LCENT, 100, 2, 2, 0, 1, 0 }, /* -a (green) axis */
- { 0, 50, 0-GAMUT_LCENT, 2, 100, 2, 1, 1, 0 }, /* +b (yellow) axis */
- };
- int i;
-
- if ((wrl = fopen(name,"w")) == NULL)
- error("Error opening VRML file '%s'\n",name);
-
- npoints = 0;
-
- fprintf(wrl,"#VRML V2.0 utf8\n");
- fprintf(wrl,"\n");
- fprintf(wrl,"# Created by the Argyll CMS\n");
- fprintf(wrl,"Transform {\n");
- fprintf(wrl,"children [\n");
- fprintf(wrl," NavigationInfo {\n");
- fprintf(wrl," type \"EXAMINE\" # It's an object we examine\n");
- fprintf(wrl," } # We'll add our own light\n");
- fprintf(wrl,"\n");
- fprintf(wrl," DirectionalLight {\n");
- fprintf(wrl," direction 0 0 -1 # Light illuminating the scene\n");
- fprintf(wrl," direction 0 -1 0 # Light illuminating the scene\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- fprintf(wrl," Viewpoint {\n");
- fprintf(wrl," position 0 0 340 # Position we view from\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- if (doaxes != 0) {
- fprintf(wrl,"# Lab axes as boxes:\n");
- for (i = 0; i < 5; i++) {
- fprintf(wrl,"Transform { translation %f %f %f\n", axes[i].x, axes[i].y, axes[i].z);
- fprintf(wrl,"\tchildren [\n");
- fprintf(wrl,"\t\tShape{\n");
- fprintf(wrl,"\t\t\tgeometry Box { size %f %f %f }\n",
- axes[i].wx, axes[i].wy, axes[i].wz);
- fprintf(wrl,"\t\t\tappearance Appearance { material Material ");
- fprintf(wrl,"{ diffuseColor %f %f %f} }\n", axes[i].r, axes[i].g, axes[i].b);
- fprintf(wrl,"\t\t}\n");
- fprintf(wrl,"\t]\n");
- fprintf(wrl,"}\n");
- }
- fprintf(wrl,"\n");
- }
-
- return wrl;
-}
-
-void
-start_line_set(FILE *wrl) {
-
- fprintf(wrl,"\n");
- fprintf(wrl,"Shape {\n");
- fprintf(wrl," geometry IndexedLineSet { \n");
- fprintf(wrl," coord Coordinate { \n");
- fprintf(wrl," point [\n");
-}
-
-void add_vertex(FILE *wrl, double pp[3]) {
-
- fprintf(wrl,"%f %f %f,\n",pp[1], pp[2], pp[0]-GAMUT_LCENT);
-
- if (paloc < (npoints+1)) {
- paloc = (paloc + 10) * 2;
- if (pary == NULL)
- pary = malloc(paloc * 3 * sizeof(double));
- else
- pary = realloc(pary, paloc * 3 * sizeof(double));
-
- if (pary == NULL)
- error ("Malloc failed");
- }
- pary[npoints].pp[0] = pp[0];
- pary[npoints].pp[1] = pp[1];
- pary[npoints].pp[2] = pp[2];
- npoints++;
-}
-
-
-void make_lines(FILE *wrl, int ppset) {
- int i, j;
-
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl," coordIndex [\n");
-
- for (i = 0; i < npoints;) {
- for (j = 0; j < ppset; j++, i++) {
- fprintf(wrl,"%d, ", i);
- }
- fprintf(wrl,"-1,\n");
- }
- fprintf(wrl," ]\n");
-
- /* Color */
- fprintf(wrl," colorPerVertex TRUE\n");
- fprintf(wrl," color Color {\n");
- fprintf(wrl," color [ # RGB colors of each vertex\n");
-
- for (i = 0; i < npoints; i++) {
- double rgb[3], Lab[3];
- Lab[0] = pary[i].pp[0];
- Lab[1] = pary[i].pp[1];
- Lab[2] = pary[i].pp[2];
- Lab2RGB(rgb, Lab);
- fprintf(wrl," %f %f %f,\n", rgb[0], rgb[1], rgb[2]);
- }
- fprintf(wrl," ] \n");
- fprintf(wrl," }\n");
- /* End color */
-
- fprintf(wrl," }\n");
- fprintf(wrl,"} # end shape\n");
-
-}
-
-void end_vrml(FILE *wrl) {
-
- fprintf(wrl,"\n");
- fprintf(wrl," ] # end of children for world\n");
- fprintf(wrl,"}\n");
-
- if (fclose(wrl) != 0)
- error("Error closing VRML file\n");
-}
-
-
-/* Convert a gamut Lab value to an RGB value for display purposes */
-static void
-Lab2RGB(double *out, double *in) {
- double L = in[0], a = in[1], b = in[2];
- double x,y,z,fx,fy,fz;
- double R, G, B;
-
- /* Scale so that black is visible */
- L = L * (100 - 40.0)/100.0 + 40.0;
-
- /* First convert to XYZ using D50 white point */
- if (L > 8.0) {
- fy = (L + 16.0)/116.0;
- y = pow(fy,3.0);
- } else {
- y = L/903.2963058;
- fy = 7.787036979 * y + 16.0/116.0;
- }
-
- fx = a/500.0 + fy;
- if (fx > 24.0/116.0)
- x = pow(fx,3.0);
- else
- x = (fx - 16.0/116.0)/7.787036979;
-
- fz = fy - b/200.0;
- if (fz > 24.0/116.0)
- z = pow(fz,3.0);
- else
- z = (fz - 16.0/116.0)/7.787036979;
-
- x *= 0.9642; /* Multiply by white point, D50 */
- y *= 1.0;
- z *= 0.8249;
-
- /* Now convert to sRGB values */
- R = x * 3.2410 + y * -1.5374 + z * -0.4986;
- G = x * -0.9692 + y * 1.8760 + z * 0.0416;
- B = x * 0.0556 + y * -0.2040 + z * 1.0570;
-
- if (R < 0.0)
- R = 0.0;
- else if (R > 1.0)
- R = 1.0;
-
- if (G < 0.0)
- G = 0.0;
- else if (G > 1.0)
- G = 1.0;
-
- if (B < 0.0)
- B = 0.0;
- else if (B > 1.0)
- B = 1.0;
-
- R = pow(R, 1.0/2.2);
- G = pow(G, 1.0/2.2);
- B = pow(B, 1.0/2.2);
-
- out[0] = R;
- out[1] = G;
- out[2] = B;
-}
-
diff --git a/gamut/viewgam.c b/gamut/viewgam.c
index 0b58269..9a7a2f5 100644
--- a/gamut/viewgam.c
+++ b/gamut/viewgam.c
@@ -26,6 +26,7 @@
#include "numlib.h"
#include "gamut.h"
#include "cgats.h"
+#include "vrml.h"
/*
This program reads one or more CGATS format triangular gamut
@@ -40,7 +41,7 @@
#undef DEBUG
-#undef HALF_HACK /* 27.0 */
+#undef HALF_HACK /* 27.0 */ /* Crude cutting plane */
void usage(char *diag, ...) {
fprintf(stderr,"View gamuts Version %s\n",ARGYLL_VERSION_STR);
@@ -53,7 +54,7 @@ void usage(char *diag, ...) {
va_end(args);
fprintf(stderr,"\n");
}
- fprintf(stderr,"usage: viewgam { [-c color] [-t trans] [-w|s] infile.gam } ... outfile.wrl\n");
+ fprintf(stderr,"usage: viewgam { [-c color] [-t trans] [-w|s] infile.gam } ... outfile%s\n",vrml_ext());
fprintf(stderr," -c color Color to make gamut, r = red, g = green, b = blue\n");
fprintf(stderr," c = cyan, m = magenta, y = yellow, e = grey, w = white\n");
fprintf(stderr," n = natural color\n");
@@ -66,13 +67,12 @@ void usage(char *diag, ...) {
fprintf(stderr," -k Add markers for prim. & sec. \"cusp\" points\n");
fprintf(stderr," -i Compute and print intersecting volume of first 2 gamuts\n");
fprintf(stderr," -I isect.gam Same as -i, but save intersection gamut to isect.gam\n");
- fprintf(stderr," outfile.wrl Name of output .wrl file\n");
+ fprintf(stderr," (Set env. ARGYLL_3D_DISP_FORMAT to VRML, X3D or X3DOM to change format)\n");
+ fprintf(stderr," outfile Base name of output %s file\n",vrml_ext());
fprintf(stderr,"\n");
exit(1);
}
-#define GCENT 50.0 /* Center of object view */
-
typedef enum {
gam_red = 0,
gam_green = 1,
@@ -86,7 +86,7 @@ typedef enum {
} gam_colors;
struct {
- double r, g, b;
+ double rgb[3];
} color_rgb[8] = {
{ 1, 0, 0 }, /* gam_red */
{ 0, 1, 0 }, /* gam_green */
@@ -172,8 +172,8 @@ main(int argc, char *argv[]) {
int doaxes = 1;
int docusps = 0;
int isect = 0;
- FILE *wrl;
- char out_name[MAXNAMEL+1];
+ vrml *wrl;
+ char out_name[MAXNAMEL+1+10];
char iout_name[MAXNAMEL+1] = "\000";;
if (argc < 3)
usage("Too few arguments, got %d expect at least 2",argc-1);
@@ -313,9 +313,9 @@ main(int argc, char *argv[]) {
/* so unwind it. */
if (ng < 2)
- usage("Not enough arguments to specify output VRML files");
+ usage("Not enough arguments to specify output %s files",vrml_format());
- strncpy(out_name,gds[--ng].in_name,MAXNAMEL); out_name[MAXNAMEL] = '\000';
+ strncpy(out_name, gds[--ng].in_name,MAXNAMEL); out_name[MAXNAMEL] = '\000';
#ifdef DEBUG
for (n = 0; n < ng; n++) {
@@ -328,102 +328,10 @@ main(int argc, char *argv[]) {
printf("Output file is '%s'\n",out_name);
#endif /* DEBUG */
- /* Open up the output file */
- if ((wrl = fopen(out_name,"w")) == NULL)
- error("Error opening output file '%s'\n",out_name);
+ /* Create the VRML object */
+ if ((wrl = new_vrml(out_name, doaxes, vrml_lab)) == NULL)
+ error("Error creating %s object '%s%s'\n",vrml_format(),out_name,vrml_ext());
- /* Write the header info */
-
- fprintf(wrl,"#VRML V2.0 utf8\n");
- fprintf(wrl,"\n");
- fprintf(wrl,"# Created by the Argyll CMS\n");
- fprintf(wrl,"Transform {\n");
- fprintf(wrl," children [\n");
- fprintf(wrl," NavigationInfo {\n");
- fprintf(wrl," type \"EXAMINE\" # It's an object we examine\n");
- fprintf(wrl," } # We'll add our own light\n");
- fprintf(wrl,"\n");
-#ifdef NEVER
- fprintf(wrl," DirectionalLight {\n");
- fprintf(wrl," direction 0 0 -1 # Light illuminating the scene\n");
- fprintf(wrl," direction 0 -1 0 # Light illuminating the scene\n");
- fprintf(wrl," }\n");
-#else
- fprintf(wrl," DirectionalLight {\n");
- fprintf(wrl," intensity 0.2\n");
- fprintf(wrl," ambientIntensity 0.1\n");
- fprintf(wrl," direction -1 -1 -1\n");
- fprintf(wrl," }\n");
- fprintf(wrl," DirectionalLight {\n");
- fprintf(wrl," intensity 0.6\n");
- fprintf(wrl," ambientIntensity 0.2\n");
- fprintf(wrl," direction 1 1 1\n");
- fprintf(wrl," }\n");
-#endif
- fprintf(wrl,"\n");
- fprintf(wrl," Viewpoint {\n");
- fprintf(wrl," position 0 0 340 # Position we view from\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
- if (doaxes) {
- /* Define the axis boxes */
- struct {
- double x, y, z; /* Box center */
- double wx, wy, wz; /* Box size */
- double r, g, b; /* Box color */
- } axes[5] = {
- { 0, 0, 50-GCENT, 2, 2, 100, .7, .7, .7 }, /* L axis */
- { 50, 0, 0-GCENT, 100, 2, 2, 1, 0, 0 }, /* +a (red) axis */
- { 0, -50, 0-GCENT, 2, 100, 2, 0, 0, 1 }, /* -b (blue) axis */
- { -50, 0, 0-GCENT, 100, 2, 2, 0, 1, 0 }, /* -a (green) axis */
- { 0, 50, 0-GCENT, 2, 100, 2, 1, 1, 0 }, /* +b (yellow) axis */
- };
-
- /* Define the labels */
- struct {
- double x, y, z;
- double size;
- char *string;
- double r, g, b;
- } labels[6] = {
- { -2, 2, -GCENT + 100 + 10, 10, "+L*", .7, .7, .7 }, /* Top of L axis */
- { -2, 2, -GCENT - 10, 10, "0", .7, .7, .7 }, /* Bottom of L axis */
- { 100 + 5, -3, 0-GCENT, 10, "+a*", 1, 0, 0 }, /* +a (red) axis */
- { -5, -100 - 10, 0-GCENT, 10, "-b*", 0, 0, 1 }, /* -b (blue) axis */
- { -100 - 15, -3, 0-GCENT, 10, "-a*", 0, 0, 1 }, /* -a (green) axis */
- { -5, 100 + 5, 0-GCENT, 10, "+b*", 1, 1, 0 }, /* +b (yellow) axis */
- };
-
- fprintf(wrl," # Lab axes as boxes:\n");
- for (n = 0; n < 5; n++) {
- fprintf(wrl," Transform { translation %f %f %f\n", axes[n].x, axes[n].y, axes[n].z);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape{\n");
- fprintf(wrl," geometry Box { size %f %f %f }\n",
- axes[n].wx, axes[n].wy, axes[n].wz);
- fprintf(wrl," appearance Appearance { material Material ");
- fprintf(wrl,"{ diffuseColor %f %f %f} }\n", axes[n].r, axes[n].g, axes[n].b);
- fprintf(wrl," }\n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- }
- fprintf(wrl," # Axes identification:\n");
- for (n = 0; n < 6; n++) {
- fprintf(wrl," Transform { translation %f %f %f\n", labels[n].x, labels[n].y, labels[n].z);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape{\n");
- fprintf(wrl," geometry Text { string [\"%s\"]\n",labels[n].string);
- fprintf(wrl," fontStyle FontStyle { family \"SANS\" style \"BOLD\" size %f }\n",
- labels[n].size);
- fprintf(wrl," }\n");
- fprintf(wrl," appearance Appearance { material Material ");
- fprintf(wrl,"{ diffuseColor %f %f %f} }\n", labels[n].r, labels[n].g, labels[n].b);
- fprintf(wrl," }\n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- }
- }
-
/* Read each input in turn */
for (n = 0; n < ng; n++) {
int i;
@@ -464,35 +372,18 @@ main(int argc, char *argv[]) {
if (pp->t[0].ftype[bf] != r_t)
error("Field LAB_B is wrong type");
- /* Write the vertexes out */
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation 0 0 0\n");
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- if (gds[n].in_rep == gam_wire) {
- fprintf(wrl," geometry IndexedLineSet {\n");
- } else {
- fprintf(wrl," geometry IndexedFaceSet {\n");
- fprintf(wrl," ccw FALSE\n");
- fprintf(wrl," convex TRUE\n");
- }
- fprintf(wrl,"\n");
- fprintf(wrl," coord Coordinate { \n");
- fprintf(wrl," point [ # Verticy coordinates\n");
+ wrl->start_line_set(wrl, 0);
/* Spit out the point values, in order. */
/* Note that a->x, b->y, L->z */
for (i = 0; i < nverts; i++) {
- double L, a, b;
- L = *((double *)pp->t[0].fdata[i][Lf]);
- a = *((double *)pp->t[0].fdata[i][af]);
- b = *((double *)pp->t[0].fdata[i][bf]);
- fprintf(wrl," %f %f %f,\n",a, b, L - GCENT);
+ double pos[3];
+ pos[0] = *((double *)pp->t[0].fdata[i][Lf]);
+ pos[1] = *((double *)pp->t[0].fdata[i][af]);
+ pos[2] = *((double *)pp->t[0].fdata[i][bf]);
+
+ wrl->add_vertex(wrl, 0, pos);
}
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
- fprintf(wrl,"\n");
/* Write the triangles/wires out */
if ((v0f = pp->find_field(pp, 1, "VERTEX_0")) < 0)
@@ -508,8 +399,6 @@ main(int argc, char *argv[]) {
if (pp->t[1].ftype[v2f] != i_t)
error("Field VERTEX_2 is wrong type");
- fprintf(wrl," coordIndex [ # Indexes of poligon Verticies \n");
-
for (i = 0; i < ntris; i++) {
int v0, v1, v2;
v0 = *((int *)pp->t[1].fdata[i][v0f]);
@@ -524,54 +413,43 @@ main(int argc, char *argv[]) {
#endif /* HALF_HACK */
if (gds[n].in_rep == gam_wire) {
- if (v0 < v1) /* Only output 1 wire of two on an edge */
- fprintf(wrl," %d, %d, -1\n", v0, v1);
- if (v1 < v2)
- fprintf(wrl," %d, %d, -1\n", v1, v2);
- if (v2 < v0)
- fprintf(wrl," %d, %d, -1\n", v2, v0);
+ int ix[2];
+ if (v0 < v1) { /* Only output 1 wire of two on an edge */
+ ix[0] = v0;
+ ix[1] = v1;
+ wrl->add_line(wrl, 0, ix);
+ }
+ if (v1 < v2) {
+ ix[0] = v1;
+ ix[1] = v2;
+ wrl->add_line(wrl, 0, ix);
+ }
+ if (v2 < v0) {
+ ix[0] = v2;
+ ix[1] = v0;
+ wrl->add_line(wrl, 0, ix);
+ }
} else {
- fprintf(wrl," %d, %d, %d, -1\n", v0, v1, v2);
+ int ix[3];
+ ix[0] = v0;
+ ix[1] = v1;
+ ix[2] = v2;
+ wrl->add_triangle(wrl, 0, ix);
}
}
- fprintf(wrl," ]\n");
- fprintf(wrl,"\n");
-
- /* Write the colors out */
- if (gds[n].in_colors == gam_natural) {
- fprintf(wrl," colorPerVertex TRUE\n");
- fprintf(wrl," color Color {\n");
- fprintf(wrl," color [ # RGB colors of each vertex\n");
-
- for (i = 0; i < nverts; i++) {
- double rgb[3], Lab[3];
- Lab[0] = *((double *)pp->t[0].fdata[i][Lf]);
- Lab[1] = *((double *)pp->t[0].fdata[i][af]);
- Lab[2] = *((double *)pp->t[0].fdata[i][bf]);
- gamut_Lab2RGB(rgb, Lab);
- fprintf(wrl," %f %f %f,\n", rgb[0], rgb[1], rgb[2]);
- }
- fprintf(wrl," ] \n");
- fprintf(wrl," }\n");
- }
- fprintf(wrl," }\n");
- fprintf(wrl," appearance Appearance { \n");
- fprintf(wrl," material Material {\n");
- if (gds[n].in_trans > 0.0) {
- fprintf(wrl," transparency %f\n", gds[n].in_trans);
- }
- fprintf(wrl," ambientIntensity 0.3\n");
- fprintf(wrl," shininess 0.5\n");
- if (gds[n].in_colors != gam_natural) {
- fprintf(wrl," emissiveColor %f %f %f\n",
- color_rgb[gds[n].in_colors].r, color_rgb[gds[n].in_colors].g, color_rgb[gds[n].in_colors].b);
+
+ /* Write the wires or triangles out */
+ if (gds[n].in_rep == gam_wire) {
+ if (gds[n].in_colors == gam_natural)
+ wrl->make_lines_vc(wrl, 0, gds[n].in_trans);
+ else
+ wrl->make_lines_cc(wrl, 0, gds[n].in_trans, color_rgb[gds[n].in_colors].rgb);
+ } else {
+ if (gds[n].in_colors == gam_natural)
+ wrl->make_triangles_vc(wrl, 0, gds[n].in_trans);
+ else
+ wrl->make_triangles(wrl, 0, gds[n].in_trans, color_rgb[gds[n].in_colors].rgb);
}
- fprintf(wrl," }\n");
- fprintf(wrl," }\n");
- fprintf(wrl," } # end Shape\n");
- fprintf(wrl," ] # end children\n");
- fprintf(wrl," } # end Transform\n");
- fprintf(wrl,"\n");
/* See if there are cusp values */
if (docusps) {
@@ -590,39 +468,19 @@ main(int argc, char *argv[]) {
break;
}
- gamut_Lab2RGB(rgb, Lab);
-
- fprintf(wrl,"\n");
- fprintf(wrl," Transform {\n");
- fprintf(wrl," translation %f %f %f\n",Lab[1], Lab[2], Lab[0]-GCENT);
- fprintf(wrl," children [\n");
- fprintf(wrl," Shape { \n");
- fprintf(wrl," geometry Sphere { radius 2.0 }\n");
- fprintf(wrl," appearance Appearance { material Material {\n");
- if (gds[n].in_trans > 0.0)
- fprintf(wrl," transparency %f\n", gds[n].in_trans);
if (gds[n].in_colors != gam_natural)
- fprintf(wrl," diffuseColor %f %f %f\n", color_rgb[gds[n].in_colors].r, color_rgb[gds[n].in_colors].g, color_rgb[gds[n].in_colors].b);
+ wrl->add_marker(wrl, Lab, color_rgb[gds[n].in_colors].rgb, 2.0);
else
- fprintf(wrl," diffuseColor %f %f %f\n", rgb[0], rgb[1], rgb[2]);
- fprintf(wrl," }\n");
- fprintf(wrl," }\n");
- fprintf(wrl," }\n");
- fprintf(wrl," ]\n");
- fprintf(wrl," }\n");
+ wrl->add_marker(wrl, Lab, NULL, 2.0);
}
- fprintf(wrl,"\n");
}
-
pp->del(pp); /* Clean up */
}
- /* Write the trailer */
- fprintf(wrl," ] # end of children for world\n");
- fprintf(wrl,"}\n");
-
- /* Close the file */
- fclose(wrl);
+ /* Write the file out */
+ if (wrl->flush(wrl))
+ error("Closing output file '%s%s'\n",out_name,vrml_ext());
+ wrl->del(wrl);
if (isect && ng >= 2) {
gamut *s, *s1, *s2;