summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/alphix.c16
-rw-r--r--target/alphix.h6
-rw-r--r--target/ofps.c109
-rw-r--r--target/ofps.h4
-rw-r--r--target/targen.c31
5 files changed, 142 insertions, 24 deletions
diff --git a/target/alphix.c b/target/alphix.c
index 68dfd48..6e5fc85 100644
--- a/target/alphix.c
+++ b/target/alphix.c
@@ -1,8 +1,10 @@
/*
- * Argyll Color Correction System
- *
* Alphabetic index class.
+ */
+
+/*
+ * Argyll Color Correction System
*
* Author: Graeme W. Gill
* Date: 22/8/2005
@@ -63,6 +65,10 @@ static int fromanat(alphix *p, char *ax) {
int cl;
int i, k, rv = 0;
+ cl = strlen(ax);
+ if (cl > p->nd) /* String is too long to be our index */
+ return -1;
+
if (p->nd > 10) {
if ((tb = malloc((p->nd+1) * sizeof(char))) == NULL)
return -1; /* Malloc error */
@@ -70,7 +76,6 @@ static int fromanat(alphix *p, char *ax) {
tb = _tb;
/* Pack the string out to the right number of digits with spaces. */
- cl = strlen(ax);
for (v = tb; cl < p->nd; v++, cl++)
*v = ' ';
strcpy(v, ax);
@@ -110,7 +115,7 @@ static char *find_start(alphix *p, char *ax) {
if (*v == p->ds[i].seq[k])
break; /* Found */
}
- if (k >= p->ds[i].n) /* Not found */
+ if (k >= p->ds[i].n) /* Not found, so we are at the start */
break;
}
return v+1;
@@ -444,6 +449,9 @@ int patch_location_order(
/* We assume that the sequences are distinguishable ... */
v = find_start(rh, ax);
+ if (*v == '\000') /* Nothing looks like a alphix */
+ return -1;
+
ri = rh->nix(rh, v);
*v = '\000';
li = lh->nix(lh, ax);
diff --git a/target/alphix.h b/target/alphix.h
index 091c191..aad5b9f 100644
--- a/target/alphix.h
+++ b/target/alphix.h
@@ -2,9 +2,11 @@
#ifndef ALPHIX_H
/*
- * Argyll Color Correction System
- *
* Alphabetic indexing class
+ */
+
+/*
+ * Argyll Color Correction System
*
* Author: Graeme W. Gill
* Date: 22/8/2005
diff --git a/target/ofps.c b/target/ofps.c
index dfcee2e..5c2219c 100644
--- a/target/ofps.c
+++ b/target/ofps.c
@@ -66,7 +66,7 @@
dimension points are aware of the lower dimension
ones. In this way the distribution of points on
lower dimensional surfaces is well spread, while
- the higher dimension points take thier positions into account.
+ the higher dimension points take their positions into account.
*/
/*
@@ -107,7 +107,7 @@
In general there are many sub-dimensions views, not all of
which would probably be regarded as important.
- To measure spread, independent voronoi tesselations of
+ To measure spread, independent voronoi tessellations of
these sub dimensions would be neededi, and they could be
used partly driver optimization (??).
@@ -717,6 +717,85 @@ default_ofps_to_percept(void *od, double *p, double *d) {
}
}
+/* Filtered perceptual lookup, used for setting up rspl cache values. */
+/* Input is device values, output L*a*b* like perceptual values. */
+static void
+filtered_ofps_to_percept(void *ss, double *p, double *d) {
+ ofps *s = (ofps *)ss;
+ double rad = 1.0/s->pcache_res; /* Filter radius = grid res. */
+ int fres = 2; /* +/- 2 around center */
+ int e, f;
+ double pw; /* Accumulated Weight */
+ double off[MXPD]; /* Offset value */
+ double out[MXPD]; /* Offset output value */
+ double roff[MXPD]; /* Reflection offset value (for clip case) */
+ double rout[MXPD]; /* Reflected offset output value */
+ DCOUNT(co, MXPD, s->di, -fres, -fres, fres+1);
+
+ if (rad > 0.05) /* Don't loose too much detail */
+ rad = 0.05;
+
+//printf("filtered called with %s\n",debPdv(s->di,d));
+
+ for (f = 0; f < s->di; f++)
+ p[f] = 0.0; /* Accumulated value */
+ pw = 0.0;
+
+ DC_INIT(co);
+
+ while (!DC_DONE(co)) {
+ double tw = 1.0;
+ int clip = 0;
+
+//printf(" sub samp at %s\n", debPiv(s->di, co));
+ for (e = 0; e < s->di; e++) {
+ double w, ov;
+ ov = ((double)co[e])/(fres+1) * rad;
+ roff[e] = off[e] = d[e] + ov;
+ if (off[e] < 0.0) {
+ off[e] = 0.0;
+ roff[e] = 0.0 - ov;
+ clip = 1;
+ }
+ else if (off[e] > 1.0) {
+ off[e] = 1.0;
+ roff[e] = 1.0 - ov;
+ clip = 1;
+ }
+//printf(" w[%d] = %f\n",e,(fres+1 - fabs((double)co[e]))/(fres+1));
+ w = (fres+1 - fabs((double)co[e]))/(fres+1);
+ tw *= w;
+ }
+//printf(" off %s wt %f\n", debPdv(s->di,off),tw);
+ s->percept(s->od, out, off);
+
+ /* For clipped case, use reflected value from reflected location */
+ if (clip) {
+ s->percept(s->od, rout, roff);
+//printf(" roff %s\n", debPdv(s->di, roff));
+//printf(" out %s\n", debPdv(s->di, out));
+//printf(" rout %s\n", debPdv(s->di, rout));
+
+ for (f = 0; f < s->di; f++)
+ out[f] = 2 * out[f] - rout[f];
+
+//printf(" eout %s\n", debPdv(s->di, out));
+ }
+ for (f = 0; f < s->di; f++)
+ p[f] += tw * out[f];
+ pw += tw;
+
+ DC_INC(co);
+ }
+ for (f = 0; f < s->di; f++)
+ p[f] /= pw;
+
+//s->percept(s->od, out, d);
+//printf(" u out %s\n", debPdv(s->di, out));
+//printf(" f out %s\n", debPdv(s->di, p));
+//printf("\n");
+}
+
/* Cached perceptual lookup */
static void
ofps_cache_percept(void *od, double *p, double *d) {
@@ -4968,27 +5047,41 @@ ofps_init_pcache(ofps *s) {
if (gr > TNPAGRIDMAXRES)
gr = TNPAGRIDMAXRES;
+#ifndef DEBUG
if (s->verb)
- printf("Perceptual cache resolution = %d\n",gr);
-
-#ifdef DEBUG
- printf("Perceptual cache resolution = %d\n",gr);
#endif
+ {
+ printf("Perceptual cache resolution = %d\n",gr);
+ printf("Seeding cache..."); fflush(stdout);
+ }
/* Create a rspl to cache the perceptual lookup */
-
if ((s->pcache = new_rspl(RSPL_NOFLAGS, s->di, s->di)) == NULL)
error("new_rspl failed");
for (e = 0; e < di; e++)
gres[e] = gr;
+ s->pcache_res = gr;
- s->pcache->set_rspl(s->pcache, RSPL_SET_APXLS, s->od, s->percept, NULL, NULL, gres, NULL, NULL);
+// s->pcache->set_rspl(s->pcache, RSPL_SET_APXLS, s->od, s->percept, NULL, NULL, gres, NULL, NULL);
+
+ /* Filtering seems to make this more robust for some profiles, less for others. */
+ if (s->percept != default_ofps_to_percept)
+ s->pcache->set_rspl(s->pcache, RSPL_NOFLAGS, s, filtered_ofps_to_percept,
+ NULL, NULL, gres, NULL, NULL);
+ else
+ s->pcache->set_rspl(s->pcache, RSPL_NOFLAGS, s->od, s->percept,
+ NULL, NULL, gres, NULL, NULL);
/* Hmm. Should we store the underlying ->percept & ->od somewhere before we overwrite it ? */
s->percept = ofps_cache_percept;
s->od = s->pcache;
+#ifndef DEBUG
+ if (s->verb)
+#endif
+ printf("done\n");
+
}
/* --------------------------------------------------- */
diff --git a/target/ofps.h b/target/ofps.h
index e2b1d55..05ca121 100644
--- a/target/ofps.h
+++ b/target/ofps.h
@@ -276,10 +276,12 @@ struct _ofps {
unsigned int lwmask; /* Last word mask */
/* Perceptual function handed in. All device values must have been */
- /* clipped before calling this, otherwise use It is assumed that */
+ /* clipped before calling this. (On running, is replaced with rspl */
+ /* cached version) */
void (*percept)(void *od, double *out, double *in);
void *od; /* Opaque data for perceptual point */
+ int pcache_res; /* Grid resolution of pcache */
rspl *pcache; /* cache of perceptual lookup */
/* Other info */
diff --git a/target/targen.c b/target/targen.c
index a29ef63..74bbe96 100644
--- a/target/targen.c
+++ b/target/targen.c
@@ -43,8 +43,10 @@
/* NOTE:
- The device model is assumed to not take xpow into account,
- hence the expected values don't reflect its effect.
+ xpow is applied over the top of the normal or supplied
+ device model, so it effectively becomes a modification
+ of the device model.
+
The general filter is applied prior to the xpow being applied.
Many of the test patch types do take it into account
when computing the ink limit.
@@ -101,6 +103,10 @@
any possible angle, none of the test data points should appear
to line up. The Argyll target generator seems to acheive this goal.
+ A final problem withe regular grids is that they can lead to
+ Runge's phenomenon, depending on the nature of the interpolation
+ algorithm used.
+
*/
#undef DEBUG
@@ -677,7 +683,7 @@ double xpow /* Extra device power, default = none */
if (xpow < 0.0)
xpow = XPOW_DEFAULT;
- s->ixpow = xpow;
+ s->ixpow = 1.0/xpow;
/* See if we have a profile */
if (profName != NULL
@@ -877,6 +883,7 @@ usage(int level, char *diag, ...) {
fprintf(stderr," -V demphasis Degree of dark region patch concentration 1.0-4.0 (default %.2f = none)\n",DEMPH_DEFAULT);
fprintf(stderr," -F L,a,b,rad Filter out samples outside Lab sphere.\n");
fprintf(stderr," -O Don't re-order display RGB patches for minimum delay\n");
+ fprintf(stderr," -U Don't filter out duplicate patches\n");
#ifdef VRML_DIAG
fprintf(stderr," -w Dump diagnostic outfilel%s file (Lab locations)\n",vrml_ext());
fprintf(stderr," -W Dump diagnostic outfiled%s file (Device locations)\n",vrml_ext());
@@ -941,8 +948,9 @@ int main(int argc, char *argv[]) {
double uilimit = -1.0; /* Underlying (pre-calibration, scale 1.0) ink limit */
double nemph = NEMPH_DEFAULT;
double demph = DEMPH_DEFAULT;
+ int dontdedupe = 0; /* Don't filter duplicate samples */
int dontreorder = 0; /* Don't re-order RGB display patches for min delay */
- int filter = 0; /* Filter values */
+ int filter = 0; /* Filter values outside given sphere */
double filt[4] = { 50,0,0,0 };
static char fname[MAXNAMEL+1] = { 0 }; /* Output file base name */
static char pname[MAXNAMEL+1] = { 0 }; /* Device profile name */
@@ -1231,6 +1239,11 @@ int main(int argc, char *argv[]) {
dontreorder = 1;
}
+ /* Don't filter out redundant patches */
+ else if (argv[fa][1] == 'U') {
+ dontdedupe = 1;
+ }
+
#ifdef VRML_DIAG
else if (argv[fa][1] == 'w') /* Lab */
dumpvrml |= 1;
@@ -1612,7 +1625,7 @@ int main(int argc, char *argv[]) {
val[e] = icx_powlike(val[e], xpow * demph);
/* See if it is already in the fixed list */
- if (fxlist != NULL) {
+ if (!dontdedupe && fxlist != NULL) {
int k;
for (k = 0; k < fxno; k++) {
for (e = 0; e < di; e++) {
@@ -1717,7 +1730,7 @@ int main(int argc, char *argv[]) {
addp = 0;
/* See if it is already in the fixed list */
- if (fxlist != NULL) {
+ if (!dontdedupe && fxlist != NULL) {
int k;
for (k = 0; k < fxno; k++) {
for (e = 0; e < di; e++) {
@@ -1802,7 +1815,7 @@ int main(int argc, char *argv[]) {
addp = 0; /* Don't add patches over ink limit */
/* See if it is already in the fixed list */
- if (addp && fxlist != NULL) {
+ if (addp && !dontdedupe && fxlist != NULL) {
int k;
for (k = 0; k < fxno; k++) {
for (e = 0; e < di; e++) {
@@ -1891,7 +1904,7 @@ int main(int argc, char *argv[]) {
addp = 1; /* Default add the point */
/* See if it is already in the fixed list */
- if (fxlist != NULL) {
+ if (!dontdedupe && fxlist != NULL) {
int k;
for (k = 0; k < fxno; k++) {
for (e = 0; e < di; e++) {
@@ -1998,7 +2011,7 @@ int main(int argc, char *argv[]) {
addp = 0; /* Don't add patches over ink limit */
/* See if it is already in the fixed list */
- if (addp && fxlist != NULL) {
+ if (addp && !dontdedupe && fxlist != NULL) {
int k;
for (k = 0; k < fxno; k++) {
for (e = 0; e < di; e++) {