diff options
Diffstat (limited to 'gamut')
-rw-r--r-- | gamut/Jamfile | 6 | ||||
-rw-r--r-- | gamut/gammap.c | 325 | ||||
-rw-r--r-- | gamut/gammap.h | 2 | ||||
-rw-r--r-- | gamut/gamut.c | 816 | ||||
-rw-r--r-- | gamut/gamut.h | 9 | ||||
-rw-r--r-- | gamut/maptest.c | 7 | ||||
-rw-r--r-- | gamut/nearsmth.c | 287 | ||||
-rw-r--r-- | gamut/nearsmth.h | 17 | ||||
-rw-r--r-- | gamut/smthtest.c | 247 | ||||
-rw-r--r-- | gamut/viewgam.c | 260 |
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; |