diff options
Diffstat (limited to 'xicc/iccgamut.c')
-rw-r--r-- | xicc/iccgamut.c | 811 |
1 files changed, 811 insertions, 0 deletions
diff --git a/xicc/iccgamut.c b/xicc/iccgamut.c new file mode 100644 index 0000000..7bd3b4c --- /dev/null +++ b/xicc/iccgamut.c @@ -0,0 +1,811 @@ + +/* + * iccgamut + * + * Produce color surface gamut of an ICC profile. + * + * Author: Graeme W. Gill + * Date: 19/3/00 + * Version: 1.00 + * + * Copyright 2000 Graeme W. Gill + * All rights reserved. + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + + +/* + * TTBD: + * To support CIACAM02 properly, need to cope with viewing parameters ? + */ + +#define SURFACE_ONLY +#define GAMRES 10.0 /* Default surface resolution */ + +#define USE_CAM_CLIP_OPT /* Use CAM space to clip in */ + +#define RGBRES 33 /* 33 */ +#define CMYKRES 17 /* 17 */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <fcntl.h> +#include <string.h> +#include <math.h> +#include "copyright.h" +#include "aconfig.h" +#include "numlib.h" +#include "icc.h" +#include "xicc.h" +#include "gamut.h" +#include "counters.h" + +static void diag_gamut(icxLuBase *p, double detail, int doaxes, + double tlimit, double klimit, char *outname); + +void usage(char *diag) { + int i; + fprintf(stderr,"Create Lab/Jab gamut plot Version %s\n",ARGYLL_VERSION_STR); + fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n"); + fprintf(stderr,"usage: iccgamut [options] profile\n"); + if (diag != NULL) + fprintf(stderr,"Diagnostic: %s\n",diag); + fprintf(stderr," -v Verbose\n"); + fprintf(stderr," -d sres Surface resolution details 1.0 - 50.0\n"); + fprintf(stderr," -w emit VRML .wrl file as well as CGATS .gam file\n"); + fprintf(stderr," -n Don't add VRML axes or white/black point\n"); + fprintf(stderr," -k Add VRML markers for prim. & sec. \"cusp\" points\n"); + fprintf(stderr," -f function f = forward*, b = backwards\n"); + fprintf(stderr," -i intent p = perceptual, r = relative colorimetric,\n"); + fprintf(stderr," s = saturation, a = absolute (default), d = profile default\n"); +// fprintf(stderr," P = absolute perceptual, S = absolute saturation\n"); + fprintf(stderr," -p oride l = Lab_PCS (default), j = %s Appearance Jab\n",icxcam_description(cam_default)); + fprintf(stderr," -o order n = normal (priority: lut > matrix > monochrome)\n"); + fprintf(stderr," r = reverse (priority: monochrome > matrix > lut)\n"); + fprintf(stderr," -l tlimit set total ink limit, 0 - 400%% (estimate by default)\n"); + fprintf(stderr," -L klimit set black ink limit, 0 - 100%% (estimate by default)\n"); + fprintf(stderr," -c viewcond set viewing conditions for %s,\n",icxcam_description(cam_default)); + fprintf(stderr," either an enumerated choice, or a series of parameter:value changes\n"); + for (i = 0; ; i++) { + icxViewCond vc; + if (xicc_enum_viewcond(NULL, &vc, i, NULL, 1, NULL) == -999) + break; + + fprintf(stderr," %s\n",vc.desc); + } + fprintf(stderr," s:surround n = auto, a = average, m = dim, d = dark,\n"); + fprintf(stderr," c = transparency (default average)\n"); + fprintf(stderr," w:X:Y:Z Adapted white point as XYZ (default media white)\n"); + fprintf(stderr," w:x:y Adapted white point as x, y\n"); + fprintf(stderr," a:adaptation Adaptation luminance in cd.m^2 (default 50.0)\n"); + fprintf(stderr," b:background Background %% of image luminance (default 20)\n"); + fprintf(stderr," l:scenewhite Scene white in cd.m^2 if surround = auto (default 250)\n"); + fprintf(stderr," f:flare Flare light %% of image luminance (default 1)\n"); + fprintf(stderr," f:X:Y:Z Flare color as XYZ (default media white)\n"); + fprintf(stderr," f:x:y Flare color as x, y\n"); + fprintf(stderr," -s Create special cube surface topology plot\n"); + fprintf(stderr,"\n"); + exit(1); +} + +int +main(int argc, char *argv[]) { + int fa,nfa; /* argument we're looking at */ + char prof_name[100]; + char *xl, out_name[100]; + icmFile *fp; + icc *icco; + xicc *xicco; + gamut *gam; + int verb = 0; + int rv = 0; + int vrml = 0; + int doaxes = 1; + int docusps = 0; + double gamres = GAMRES; /* Surface resolution */ + int special = 0; /* Special surface plot */ + int fl = 0; /* luobj flags */ + icxInk ink; /* Ink parameters */ + int tlimit = -1; /* Total ink limit as a % */ + int klimit = -1; /* Black ink limit as a % */ + icxViewCond vc; /* Viewing Condition for CIECAM */ + int vc_e = -1; /* Enumerated viewing condition */ + int vc_s = -1; /* Surround override */ + double vc_wXYZ[3] = {-1.0, -1.0, -1.0}; /* Adapted white override in XYZ */ + double vc_wxy[2] = {-1.0, -1.0}; /* Adapted white override in x,y */ + double vc_a = -1.0; /* Adapted luminance */ + double vc_b = -1.0; /* Background % overide */ + double vc_l = -1.0; /* Scene luminance override */ + double vc_f = -1.0; /* Flare % overide */ + double vc_fXYZ[3] = {-1.0, -1.0, -1.0}; /* Flare color override in XYZ */ + double vc_fxy[2] = {-1.0, -1.0}; /* Flare color override in x,y */ + + icxLuBase *luo; + + /* Lookup parameters */ + icmLookupFunc func = icmFwd; /* Default */ + icRenderingIntent intent = -1; /* Default */ + icColorSpaceSignature pcsor = icSigLabData; /* Default */ + icmLookupOrder order = icmLuOrdNorm; /* Default */ + + error_program = argv[0]; + + if (argc < 2) + usage("Too few parameters"); + + /* Process the arguments */ + for(fa = 1;fa < argc;fa++) { + nfa = fa; /* skip to nfa if next argument is used */ + if (argv[fa][0] == '-') { /* Look for any flags */ + char *na = NULL; /* next argument after flag, null if none */ + + if (argv[fa][2] != '\000') + na = &argv[fa][2]; /* next is directly after flag */ + else { + if ((fa+1) < argc) { + if (argv[fa+1][0] != '-') { + nfa = fa + 1; + na = argv[nfa]; /* next is seperate non-flag argument */ + } + } + } + + if (argv[fa][1] == '?') + usage(NULL); + + /* function */ + else if (argv[fa][1] == 'f' || argv[fa][1] == 'F') { + fa = nfa; + if (na == NULL) usage("No parameter after flag -f"); + switch (na[0]) { + case 'f': + case 'F': + func = icmFwd; + break; + case 'b': + case 'B': + func = icmBwd; + break; + default: + usage("Unrecognised parameter after flag -f"); + } + } + + /* Intent */ + else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') { + fa = nfa; + if (na == NULL) usage("No parameter after flag -i"); + switch (na[0]) { + case 'd': + intent = icmDefaultIntent; + break; + case 'a': + intent = icAbsoluteColorimetric; + break; + case 'p': + intent = icPerceptual; + break; + case 'r': + intent = icRelativeColorimetric; + break; + case 's': + intent = icSaturation; + break; + /* Argyll special intents to check spaces underlying */ + /* icxPerceptualAppearance & icxSaturationAppearance */ + case 'P': + intent = icmAbsolutePerceptual; + break; + case 'S': + intent = icmAbsoluteSaturation; + break; + default: + usage("Unrecognised parameter after flag -i"); + } + } + + /* Search order */ + else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') { + fa = nfa; + if (na == NULL) usage("No parameter after flag -o"); + switch (na[0]) { + case 'n': + case 'N': + order = icmLuOrdNorm; + break; + case 'r': + case 'R': + order = icmLuOrdRev; + break; + default: + usage("Unrecognised parameter after flag -o"); + } + } + + /* PCS override */ + else if (argv[fa][1] == 'p' || argv[fa][1] == 'P') { + fa = nfa; + if (na == NULL) usage("No parameter after flag -p"); + switch (na[0]) { + case 'l': + pcsor = icSigLabData; + break; + case 'j': + pcsor = icxSigJabData; + break; + default: + usage("Unrecognised parameter after flag -p"); + } + } + + /* Verbosity */ + else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') { + verb = 1; + } + /* VRML output */ + else if (argv[fa][1] == 'w' || argv[fa][1] == 'W') { + vrml = 1; + } + /* No axis output in vrml */ + else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') { + doaxes = 0; + } + /* Do cusp markers in vrml */ + else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') { + docusps = 1; + } + /* Special */ + else if (argv[fa][1] == 's' || argv[fa][1] == 'S') { + special = 1; + } + /* Ink limit */ + else if (argv[fa][1] == 'l') { + fa = nfa; + if (na == NULL) usage("No parameter after flag -l"); + tlimit = atoi(na); + } + + else if (argv[fa][1] == 'L') { + fa = nfa; + if (na == NULL) usage("No parameter after flag -L"); + klimit = atoi(na); + } + + + /* Surface Detail */ + else if (argv[fa][1] == 'd' || argv[fa][1] == 'D') { + fa = nfa; + if (na == NULL) usage("No parameter after flag -d"); + gamres = atof(na); + if (gamres < 0.1 || gamres > 50.0) + usage("Parameter after flag -d seems out of range"); + } + + /* Viewing conditions */ + else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') { + fa = nfa; + if (na == NULL) usage("No parameter after flag -c"); +#ifdef NEVER + if (na[0] >= '0' && na[0] <= '9') { + vc_e = atoi(na); + } else +#endif + if (na[1] != ':') { + if ((vc_e = xicc_enum_viewcond(NULL, NULL, -2, na, 1, NULL)) == -999) + usage("Urecognised Enumerated Viewing conditions"); + } else if (na[0] == 's' || na[0] == 'S') { + if (na[1] != ':') + usage("Unrecognised parameters after -cs"); + if (na[2] == 'n' || na[2] == 'N') { + vc_s = vc_none; /* Automatic from Lv */ + } else if (na[2] == 'a' || na[2] == 'A') { + vc_s = vc_average; + } else if (na[2] == 'm' || na[2] == 'M') { + vc_s = vc_dim; + } else if (na[2] == 'd' || na[2] == 'D') { + vc_s = vc_dark; + } else if (na[2] == 'c' || na[2] == 'C') { + vc_s = vc_cut_sheet; + } else + usage("Unrecognised parameters after -cs:"); + } else if (na[0] == 'w' || na[0] == 'W') { + double x, y, z; + if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) { + vc_wXYZ[0] = x; vc_wXYZ[1] = y; vc_wXYZ[2] = z; + } else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) { + vc_wxy[0] = x; vc_wxy[1] = y; + } else + usage("Unrecognised parameters after -cw"); + } else if (na[0] == 'a' || na[0] == 'A') { + if (na[1] != ':') + usage("Unrecognised parameters after -ca"); + vc_a = atof(na+2); + } else if (na[0] == 'b' || na[0] == 'B') { + if (na[1] != ':') + usage("Unrecognised parameters after -cb"); + vc_b = atof(na+2); + } else if (na[0] == 'l' || na[0] == 'L') { + if (na[1] != ':') + usage("Viewing conditions (-[cd]l) missing ':'"); + vc_l = atof(na+2); + } else if (na[0] == 'f' || na[0] == 'F') { + double x, y, z; + if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) { + vc_fXYZ[0] = x; vc_fXYZ[1] = y; vc_fXYZ[2] = z; + } else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) { + vc_fxy[0] = x; vc_fxy[1] = y; + } else if (sscanf(na+1,":%lf",&x) == 1) { + vc_f = x; + } else + usage("Unrecognised parameters after -cf"); + } else + usage("Unrecognised parameters after -c"); + } + else + usage("Unknown flag"); + } else + break; + } + + if (intent == -1) { + if (pcsor == icxSigJabData) + intent = icRelativeColorimetric; /* Default to icxAppearance */ + else + intent = icAbsoluteColorimetric; /* Default to icAbsoluteColorimetric */ + } + + if (fa >= argc || argv[fa][0] == '-') usage("Expected profile name"); + strcpy(prof_name,argv[fa]); + + /* Open up the profile for reading */ + if ((fp = new_icmFileStd_name(prof_name,"r")) == NULL) + error ("Can't open file '%s'",prof_name); + + if ((icco = new_icc()) == NULL) + error ("Creation of ICC object failed"); + + if ((rv = icco->read(icco,fp,0)) != 0) + error ("%d, %s",rv,icco->err); + + if (verb) { + icmFile *op; + if ((op = new_icmFileStd_fp(stdout)) == NULL) + error ("Can't open stdout"); + icco->header->dump(icco->header, op, 1); + op->del(op); + } + + /* Wrap with an expanded icc */ + if ((xicco = new_xicc(icco)) == NULL) + error ("Creation of xicc failed"); + + /* Set the ink limits */ + icxDefaultLimits(xicco, &ink.tlimit, tlimit/100.0, &ink.klimit, klimit/100.0); + + if (verb) { + if (ink.tlimit >= 0.0) + printf("Total ink limit assumed is %3.0f%%\n",100.0 * ink.tlimit); + if (ink.klimit >= 0.0) + printf("Black ink limit assumed is %3.0f%%\n",100.0 * ink.klimit); + } + + /* Setup a safe ink generation (not used) */ + ink.KonlyLmin = 0; /* Use normal black Lmin for locus */ + ink.k_rule = icxKluma5k; + ink.c.Ksmth = ICXINKDEFSMTH; /* Default smoothing */ + ink.c.Kskew = ICXINKDEFSKEW; /* default curve skew */ + ink.c.Kstle = 0.0; /* Min K at white end */ + ink.c.Kstpo = 0.0; /* Start of transition is at white */ + ink.c.Kenle = 1.0; /* Max K at black end */ + ink.c.Kenpo = 1.0; /* End transition at black */ + ink.c.Kshap = 1.0; /* Linear transition */ + + /* Setup the default viewing conditions */ + if (xicc_enum_viewcond(xicco, &vc, -1, NULL, 0, NULL) == -2) + error ("%d, %s",xicco->errc, xicco->err); + + if (vc_e != -1) + if (xicc_enum_viewcond(xicco, &vc, vc_e, NULL, 0, NULL) == -2) + error ("%d, %s",xicco->errc, xicco->err); + if (vc_s >= 0) + vc.Ev = vc_s; + if (vc_wXYZ[1] > 0.0) { + /* Normalise it to current media white */ + vc.Wxyz[0] = vc_wXYZ[0]/vc_wXYZ[1] * vc.Wxyz[1]; + vc.Wxyz[2] = vc_wXYZ[2]/vc_wXYZ[1] * vc.Wxyz[1]; + } + if (vc_wxy[0] >= 0.0) { + double x = vc_wxy[0]; + double y = vc_wxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */ + double z = 1.0 - x - y; + vc.Wxyz[0] = x/y * vc.Wxyz[1]; + vc.Wxyz[2] = z/y * vc.Wxyz[1]; + } + if (vc_a >= 0.0) + vc.La = vc_a; + if (vc_b >= 0.0) + vc.Yb = vc_b/100.0; + if (vc_l >= 0.0) + vc.Lv = vc_l; + if (vc_f >= 0.0) + vc.Yf = vc_f/100.0; + if (vc_fXYZ[1] > 0.0) { + /* Normalise it to current media white */ + vc.Fxyz[0] = vc_fXYZ[0]/vc_fXYZ[1] * vc.Fxyz[1]; + vc.Fxyz[2] = vc_fXYZ[2]/vc_fXYZ[1] * vc.Fxyz[1]; + } + if (vc_fxy[0] >= 0.0) { + double x = vc_fxy[0]; + double y = vc_fxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */ + double z = 1.0 - x - y; + vc.Fxyz[0] = x/y * vc.Fxyz[1]; + vc.Fxyz[2] = z/y * vc.Fxyz[1]; + } + + fl |= ICX_CLIP_NEAREST; /* Don't setup rev uncessarily */ + +#ifdef USE_CAM_CLIP_OPT + fl |= ICX_CAM_CLIP; +#endif + +#ifdef NEVER + printf("~1 output space flags = 0x%x\n",fl); + printf("~1 output space intent = %s\n",icx2str(icmRenderingIntent,intent)); + printf("~1 output space pcs = %s\n",icx2str(icmColorSpaceSignature,pcsor)); + printf("~1 output space viewing conditions =\n"); xicc_dump_viewcond(&vc); + printf("~1 output space inking =\n"); xicc_dump_inking(&ink); +#endif + + strcpy(out_name, prof_name); + if ((xl = strrchr(out_name, '.')) == NULL) /* Figure where extention is */ + xl = out_name + strlen(out_name); + + strcpy(xl,".gam"); + + /* Get a expanded color conversion object */ + if ((luo = xicco->get_luobj(xicco, fl, func, intent, pcsor, order, &vc, &ink)) == NULL) + error ("%d, %s",xicco->errc, xicco->err); + + if (special) { + if (func != icmFwd) + error("Must be forward direction for special plot"); + strcpy(xl,".wrl"); + diag_gamut(luo, gamres, doaxes, tlimit/100.0, klimit/100.0, out_name); + } else { + /* Creat a gamut surface */ + if ((gam = luo->get_gamut(luo, gamres)) == NULL) + error ("%d, %s",xicco->errc, xicco->err); + + if (gam->write_gam(gam,out_name)) + error ("write gamut failed on '%s'",out_name); + + if (vrml) { + strcpy(xl,".wrl"); + if (gam->write_vrml(gam,out_name, doaxes, docusps)) + error ("write vrml failed on '%s'",out_name); + } + + if (verb) { + printf("Total volume of gamut is %f cubic colorspace units\n",gam->volume(gam)); + } + gam->del(gam); + } + + luo->del(luo); /* Done with lookup object */ + + xicco->del(xicco); /* Expansion wrapper */ + icco->del(icco); /* Icc */ + fp->del(fp); + + + return 0; +} + +/* -------------------------------------------- */ +/* Code for special gamut surface plot */ + +#define GAMUT_LCENT 50 + +/* Create a diagnostic gamut, illustrating */ +/* device space "fold-over" */ +static void diag_gamut( +icxLuBase *p, /* Lookup object */ +double detail, /* Gamut resolution detail */ +int doaxes, /* Do Lab axes */ +double tlimit, /* Total ink limit */ +double klimit, /* K ink limit */ +char *outname /* Output VRML file */ +) { + int i, j; + 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 vix; /* Vertex index */ + DCOUNT(coa, MXDI, p->inputChan, 0, 0, 2); + + double col[1 << MXDI][3]; /* Color asigned to each major vertex */ + int res; + + if (tlimit < 0.0) + tlimit = p->inputChan; + if (klimit < 0.0) + klimit = 1.0; + + /* Asign some colors to the combination nodes */ + for (i = 0; i < (1 << p->inputChan); i++) { + int a, b, c, j; + double h; + + j = (i ^ 0x5a5a5a5a) % (1 << p->inputChan); + h = (double)j/((1 << p->inputChan)-1); + + /* Make fully saturated with chosen hue */ + if (h < 1.0/3.0) { + a = 0; + b = 1; + c = 2; + } else if (h < 2.0/3.0) { + a = 1; + b = 2; + c = 0; + h -= 1.0/3.0; + } else { + a = 2; + b = 0; + c = 1; + h -= 2.0/3.0; + } + h *= 3.0; + + col[i][a] = (1.0 - h); + col[i][b] = h; + col[i][c] = d_rand(0.0, 1.0); + } + + if (detail > 0.0) + res = (int)(100.0/detail); /* Establish an appropriate sampling density */ + else + res = 4; + + if (res < 2) + res = 2; + + if ((wrl = fopen(outname,"w")) == NULL) + error("Error opening wrl output file '%s'",outname); + + /* 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 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"); + } + 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," solid FALSE\n"); /* Don't back face cull */ + fprintf(wrl," convex TRUE\n"); + fprintf(wrl,"\n"); + fprintf(wrl," coord Coordinate { \n"); + fprintf(wrl," point [ # Verticy coordinates\n"); + + + /* Itterate over all the faces in the device space */ + /* generating the vertx positions. */ + DC_INIT(coa); + vix = 0; + while(!DC_DONE(coa)) { + int e, m1, m2; + double in[MXDI]; + double inl[MXDI]; + double out[3]; + double sum; + + /* Scan only device surface */ + for (m1 = 0; m1 < p->inputChan; m1++) { + if (coa[m1] != 0) + continue; + + for (m2 = m1 + 1; m2 < p->inputChan; m2++) { + int x, y; + + if (coa[m2] != 0) + continue; + + for (e = 0; e < p->inputChan; e++) + in[e] = (double)coa[e]; /* Base value */ + + /* Scan over 2D device space face */ + for (x = 0; x < res; x++) { /* step over surface */ + in[m1] = x/(res - 1.0); + for (y = 0; y < res; y++) { + in[m2] = y/(res - 1.0); + + for (sum = 0.0, e = 0; e < p->inputChan; e++) { + sum += inl[e] = in[e]; + } + if (sum >= tlimit) { + for (e = 0; e < p->inputChan; e++) + inl[e] *= tlimit/sum; + } + if (p->inputChan >= 3 && inl[3] >= klimit) + inl[3] = klimit; + p->lookup(p, out, inl); + fprintf(wrl,"%f %f %f,\n",out[1], out[2], out[0]-50.0); + vix++; + } + } + } + } + /* Increment index within block */ + DC_INC(coa); + } + + fprintf(wrl," ]\n"); + fprintf(wrl," }\n"); + fprintf(wrl,"\n"); + fprintf(wrl," coordIndex [ # Indexes of poligon Verticies \n"); + + /* Itterate over all the faces in the device space */ + /* generating the quadrilateral indexes. */ + DC_INIT(coa); + vix = 0; + while(!DC_DONE(coa)) { + int e, m1, m2; + double in[MXDI]; + + /* Scan only device surface */ + for (m1 = 0; m1 < p->inputChan; m1++) { + if (coa[m1] != 0) + continue; + + for (m2 = m1 + 1; m2 < p->inputChan; m2++) { + int x, y; + + if (coa[m2] != 0) + continue; + + for (e = 0; e < p->inputChan; e++) + in[e] = (double)coa[e]; /* Base value */ + + /* Scan over 2D device space face */ + /* Only output quads under the total ink limit */ + /* Scan over 2D device space face */ + for (x = 0; x < res; x++) { /* step over surface */ + for (y = 0; y < res; y++) { + if (x < (res-1) && y < (res-1)) { + fprintf(wrl,"%d, %d, %d, %d, -1\n", + vix, vix + 1, vix + 1 + res, vix + res); + } + vix++; + } + } + } + } + /* Increment index within block */ + DC_INC(coa); + } + + 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"); + + /* Itterate over all the faces in the device space */ + /* generating the vertx colors. */ + DC_INIT(coa); + vix = 0; + while(!DC_DONE(coa)) { + int e, m1, m2; + double in[MXDI]; + + /* Scan only device surface */ + for (m1 = 0; m1 < p->inputChan; m1++) { + if (coa[m1] != 0) + continue; + + for (m2 = m1 + 1; m2 < p->inputChan; m2++) { + int x, y; + + if (coa[m2] != 0) + continue; + + for (e = 0; e < p->inputChan; e++) + in[e] = (double)coa[e]; /* Base value */ + + /* Scan over 2D device space face */ + for (x = 0; x < res; x++) { /* step over surface */ + double xb = x/(res - 1.0); + for (y = 0; y < res; y++) { + int v0, v1, v2, v3; + double yb = y/(res - 1.0); + double rgb[3]; + + for (v0 = 0, e = 0; e < p->inputChan; e++) + v0 |= coa[e] ? (1 << e) : 0; /* Binary index */ + + v1 = v0 | (1 << m2); /* Y offset */ + v2 = v0 | (1 << m2) | (1 << m1); /* X+Y offset */ + v3 = v0 | (1 << m1); /* Y offset */ + + /* Linear interp between the main verticies */ + for (j = 0; j < 3; j++) { + rgb[j] = (1.0 - yb) * (1.0 - xb) * col[v0][j] + + yb * (1.0 - xb) * col[v1][j] + + (1.0 - yb) * xb * col[v3][j] + + yb * xb * col[v2][j]; + } + fprintf(wrl,"%f %f %f,\n",rgb[1], rgb[2], rgb[0]); + vix++; + } + } + } + } + /* Increment index within block */ + DC_INC(coa); + } + + 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"); + + fprintf(wrl,"\n"); + fprintf(wrl," ] # end of children for world\n"); + fprintf(wrl,"}\n"); + + if (fclose(wrl) != 0) + error("Error closing output file '%s'",outname); +} + |