diff options
Diffstat (limited to 'imdi/imdi_tab.c')
-rw-r--r-- | imdi/imdi_tab.c | 803 |
1 files changed, 803 insertions, 0 deletions
diff --git a/imdi/imdi_tab.c b/imdi/imdi_tab.c new file mode 100644 index 0000000..4f448f0 --- /dev/null +++ b/imdi/imdi_tab.c @@ -0,0 +1,803 @@ + +/* Integer Multi-Dimensional Interpolation */ + +/* + * Copyright 2000 - 2007 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. + */ + +/* + * Run time table allocater and initialiser + * + * The function here that knows how to create the + * appropriate run time tables for our chosen kernel, + * and the type color mapping we want to perform. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <stdarg.h> +#include <string.h> + +#include "imdi.h" +#include "imdi_tab.h" + +#undef VERBOSE +#undef ASSERTS /* Check asserts */ + +#ifdef ASSERTS +#include <numlib.h> +#endif + + + +typedef unsigned char byte; + +/* Left shift, handles >= 32 properly */ +#define LSHIFT(aa, bb) ((bb) <= 31 ? ((aa) << (bb)) : (((aa) << 31) << ((bb)-31))) + +/* The big value type used to represent table entries */ +#ifdef ALLOW64 +typedef unsigned longlong bvt; +#else +typedef unsigned long bvt; +#endif + +/* Specific entry size write routine */ + +void write_uchar( +byte *p, +bvt v +) { + *((unsigned char *)p) = (unsigned char)v; +} + +void write_ushort( +byte *p, +bvt v +) { + *((unsigned short *)p) = (unsigned short)v; +} + +void write_uint( +byte *p, +bvt v +) { + *((unsigned int *)p) = (unsigned int)v; +} + +void write_ulong( +byte *p, +bvt v +) { + *((unsigned long *)p) = (unsigned long)v; +} + +#ifdef ALLOW64 +void write_ulonglong( +byte *p, +bvt v +) { + *((unsigned longlong *)p) = (unsigned longlong)v; +} +#endif /* ALLOW64 */ + +void write_default( +byte *p, +bvt v +) { + fprintf(stderr,"imdi_tabl: internal failure - unexpected write size!\n"); + exit(-1); +} + +/* Array of write routines */ +void (*write_entry[16])(byte *p, bvt v); + +static void +init_write_tab(void) { + int i; + + for (i = 0; i < 16; i++) + write_entry[i] = write_default; /* Make sure any un-inited access bombs */ + + write_entry[sizeof(unsigned char)] = write_uchar; + write_entry[sizeof(unsigned short)] = write_ushort; + write_entry[sizeof(unsigned int)] = write_uint; + write_entry[sizeof(unsigned long)] = write_ulong; +#ifdef ALLOW64 + write_entry[sizeof(unsigned longlong)] = write_ulonglong; +#endif /* ALLOW64 */ +} + + +/* Input offset adjustment table */ +double in_adj[] = { + 8.0324820232182659e+281, 1.3051220361353854e+214, 1.5654418860154115e-076, + 6.6912978722165055e+281, 1.2369092402930559e+277, 1.4097588049607207e-308, + 7.7791723264456369e-260, 3.6184161952648606e+238, 5.8235640814908141e+180, + 9.1271554315814989e-072, 5.4310198502711138e+241, 2.7935452404894958e+275, + -2.9408705449902027e+003 +}; + + +/* Table creation function */ +imdi_imp * +imdi_tab( + genspec *gs, /* Pointer to gen spec */ + tabspec *ts, /* Pointer to table spec */ + imdi_conv cnv, /* Runtime argument conversion needed */ + imdi_pixrep irep, /* High level input pixel representation to match */ + imdi_pixrep orep, /* High level output pixel representation to match */ + void (*interp)(struct _imdi *s, void **outp, int outst, /* Underlying conversion function */ + void **inp, int inst, + unsigned int npixels), + + int *inm, /* Input raster channel to callback channel mapping, NULL for none. */ + int *outm, /* Output raster channel to callback channel mapping, NULL for none. */ + imdi_ooptions oopt, /* Output per channel options (Callback channel, NOT output channel) */ + unsigned int *checkv, /* Output channel check values (Callback channel, NULL for none == 0. */ + + /* Callbacks to lookup the mdi table values */ + void (*input_curves) (void *cntx, double *out_vals, double *in_vals), + void (*md_table) (void *cntx, double *out_vals, double *in_vals), + void (*output_curves)(void *cntx, double *out_vals, double *in_vals), + void *cntx /* Context to callbacks */ +) { + static int inited = 0; + static int bigend = 0; + int i, e, f; + imdi_imp *it; + unsigned long etest = 0xff; + int idinc[IXDI+1]; /* Increment for each dimension of interp table. */ + int ibdinc[IXDI+1]; /* idinc[] in bytes */ + int sdinc[IXDI+1]; /* Increment for each dimension of simplex table. */ + int sbdinc[IXDI+1]; /* sdinc[] in bytes */ + +#ifdef VERBOSE + printf("imdi_tab called\n"); +#endif + + if (inited == 0) { + init_write_tab(); + if (*((unsigned char *)&etest) == 0xff) + bigend = 0; /* Little endian */ + else + bigend = 1; /* Big endian */ + inited = 1; + } + + if ((it = (imdi_imp *)calloc(1, sizeof(imdi_imp))) == NULL) { +#ifdef VERBOSE + printf("malloc imdi_imp size %d failed\n",sizeof(imdi_imp)); +#endif + return NULL; /* Should we signal error ? How ? */ + } + + it->size = sizeof(imdi_imp); +#ifdef VERBOSE + printf("Allocated imdi_imp structure size %u\n",it->size); +#endif /* VERBOSE */ + + /* Set runtime matching conversion provided */ + it->cnv = cnv; + it->id = gs->id; + it->od = gs->od; + it->cirep = irep; /* Pixel representation interp is called with */ + it->corep = orep; + it->firep = gs->irep; /* Pixel representation of function we are going to use */ + it->forep = gs->orep; + it->interp = interp; + it->checkf = 0; + + /* Compute number of written channels (allow for skip) */ + it->wod = it->od; + for (i = 0; i < it->od; i++) { + if ((oopt & OOPT(oopts_skip,i)) != 0) + it->wod--; + } + + /* Setup the raster to callback channel mappings */ + if (inm != NULL) { + for (e = 0; e < it->id; e++) + it->it_map[e] = inm[e]; /* Copy input */ + } else { + for (e = 0; e < it->id; e++) + it->it_map[e] = e; /* Direct mapping */ + } + if (outm != NULL) { + for (e = 0; e < it->od; e++) + it->im_map[e] = outm[e]; /* Copy input */ + } else { + for (e = 0; e < it->od; e++) + it->im_map[e] = e; /* Direct mapping */ + } + if (checkv != NULL) { + for (e = 0; e < it->od; e++) + it->checkv[e] = checkv[it->im_map[e]]; /* Copy input and convert to Output index */ + } else { + for (e = 0; e < it->od; e++) + it->checkv[e] = 0; /* Set to zero */ + } + + /* Compute interp and simplex table dimension increments & total sizes */ + idinc[0] = 1; + ibdinc[0] = ts->im_ts; + for (e = 1; e <= it->id; e++) { + idinc[e] = idinc[e-1] * gs->itres; + ibdinc[e] = ibdinc[e-1] * gs->itres; + } + + if (!ts->sort) { + sdinc[0] = 1; + sbdinc[0] = ts->sm_ts; + for (e = 1; e <= it->id; e++) { + sdinc[e] = sdinc[e-1] * gs->stres; + sbdinc[e] = sbdinc[e-1] * gs->stres; + } + } + + /* First we setup the input tables */ + for (e = 0; e < it->id; e++) { + byte *t, *p; /* Pointer to input table, entry pointer */ + int ne; /* Number of entries */ + int ex; /* Entry index */ + double iaf; + int ix = 0; /* Extract flag */ + + /* Compute number of entries */ + if (ts->it_ix && !gs->in.packed) { /* Input is the whole bpch[] size */ + ix = 1; /* Need to do extraction in lookup */ + if (gs->in.pint) { + ne = (1 << (gs->in.bpch[0])); /* Same size used for all input tables */ + } else { + ne = (1 << (gs->in.bpch[e])); /* This input channels size */ + } + } else { /* Input is the value size */ + ne = (1 << (gs->in.bpv[e])); /* This input values size */ + } + + /* Allocate the table */ + if ((t = (byte *)malloc(ts->it_ts * ne)) == NULL) { +#ifdef VERBOSE + printf("malloc imdi input table size %d failed\n",ts->it_ts * ne); +#endif + return NULL; /* Should we signal error ? How ? */ + } + it->size += ts->it_ts * ne; +#ifdef VERBOSE + printf("Allocated input table %d size %u = %u * %u\n",e, ts->it_ts * ne,ts->it_ts,ne); +#endif /* VERBOSE */ + + /* Comput input adjustment factor */ + for (iaf = 0.0, i = 0; i < (sizeof(in_adj)/sizeof(double)-1); i++) + iaf += log(in_adj[i]); + iaf += in_adj[i]; + + /* For each possible input value, compute the entry value */ + for (ex = 0, p = t; ex < ne; ex++, p += ts->it_ts) { + int iiv; /* Integer input value */ + int ivr; /* Input value range */ + int isb; /* Input sign bit/signed to offset displacement */ + double riv; /* Real input value, 0.0 - 1.0 */ + double rtv; /* Real transformed value, 0.0 - 1.0 */ + double rmi; /* Real interpolation table index */ + double rsi; /* Real simplex index */ + int imi; /* Interpiolation table index */ + int isi = 0; /* Integer simplex index */ + int iwe = 0; /* Integer weighting value */ + int vo = 0; /* Vertex offset value */ + + if (ix) { /* Extract value from index */ + ivr = ((1 << (gs->in.bpv[e])) -1); + iiv = (ex >> gs->in.bov[e]) & ((1 << (gs->in.bpv[e])) -1); + } else { + ivr = (ne - 1); /* (Should be bpv[e], but take no chances!) */ + iiv = ex; /* Input value is simply index */ + } + isb = ivr & ~(((unsigned int)ivr) >> 1); /* Top bit */ + if (gs->in_signed & (1 << e)) /* Treat input as signed */ + iiv = (iiv & isb) ? iiv - isb : iiv + isb; /* Convert to offset from signed */ + riv = (double) iiv / (double)ivr; /* Compute floating point */ + { + double civ[IXDI], cov[IXDI]; + for (f = 0; f < it->id; f++) + civ[f] = riv; + input_curves(cntx, cov, civ); /* Lookup the input table transform */ + rtv = iaf * cov[it->it_map[e]]; + } + if (rtv < 0.0) /* Guard against sillies */ + rtv = 0.0; + else if (rtv > 1.0) + rtv = 1.0; + + /* divide into interp base and cube sub index */ + rmi = rtv * (gs->itres - 1); + imi = (int)floor(rmi); /* Interp. entry coordinate */ + if (imi >= (gs->itres-1)) /* Keep cube base one row back from far edge */ + imi = gs->itres-2; + rsi = rmi - (double)imi; /* offset into entry cube */ + if (ts->sort) { + iwe = (int)((rsi * (1 << gs->prec)) + 0.5); /* Weighting scale */ + vo = idinc[e] * ts->vo_om; /* Vertex offset */ + } else { + isi = (int)((rsi * gs->stres) + 0.5); + if (isi == gs->stres) { /* Keep simplex index within table */ + isi = 0; + imi++; /* Move to next interp. lattice */ + } + isi *= sdinc[e]; /* Convert the raw indexes into offset in this dim */ + } + imi *= idinc[e]; /* Convert the raw indexes into offset in this dim */ + +#ifdef ASSERTS + /* ~~~ needs fixing for sort ~~~~ */ + if ((imi & (LSHIFT(1,ts->it_ab)-1)) != imi) + error("imdi_tab assert: (imi & ((1 << ts->it_ab)-1)) != imi, imi = 0x%x, it_ab = 0x%x\n",imi,ts->it_ab); + if (imi >= idinc[it->id]) + error("imdi_tab assert: imi >= idinc[it->id]\n"); + if ((isi & (LSHIFT(1,ts->sx_ab)-1)) != isi) + error("imdi_tab assert: (isi & ((1 << ts->sx_ab)-1)) != isi, isi = 0x%x, sx_ab = 0x%x\n",isi,ts->sx_ab); + if (!ts->sort && isi >= sdinc[it->id]) + error("imdi_tab assert: isi >= sdinc[it->id]\n"); +#endif + + /* Now stuff them into the table entry */ + if (ts->sort) { + if (ts->it_xs) { /* Separate interp index and weight/offset*/ + if (ts->wo_xs) { /* All 3 are separate */ + write_entry[ts->ix_es](p + ts->ix_eo, imi); + write_entry[ts->we_es](p + ts->we_eo, iwe); + write_entry[ts->vo_es](p + ts->vo_eo, vo); + } else { + bvt iwo; + + iwo = ((bvt)iwe << ts->vo_ab) | vo; /* Combined weight+vertex offset */ + write_entry[ts->ix_es](p + ts->ix_eo, imi); + write_entry[ts->wo_es](p + ts->wo_eo, iwo); + } + } else { /* All 3 are combined */ + bvt iit; + + iit = ((((bvt)imi << ts->we_ab) | (bvt)iwe) << ts->vo_ab) | vo; + write_entry[ts->it_ts](p, iit); + } + } else { + if (ts->it_xs) { /* Separate interp index and weight/offset*/ + write_entry[ts->ix_es](p + ts->ix_eo, imi); + write_entry[ts->sx_es](p + ts->sx_eo, isi); + } else { + bvt iit; + + iit = ((bvt)imi << ts->sx_ab) | isi; /* Combine interp and simplex indexes */ + write_entry[ts->it_ts](p, iit); + } + } + } + + /* Put table into place */ + it->in_tables[e] = (void *)t; + } + it->nintabs = e; + + /* Setup the interpolation table */ + { + byte *t, *p; /* Pointer to interp table, pointer to total entry */ + PHILBERT(phc) /* Pseudo Hilbert counter */ + double vscale; /* Value scale for fixed point */ + int vsize; /* Fixed point storage size */ + + if (ts->im_cd) + vsize = (gs->prec * 2)/8; /* Fixed point entry & computation size */ + else + vsize = gs->prec/8; /* Fixed point entry size */ + vscale = (1 << gs->prec) -0.50000001; + /* Value scale for fixed point padding */ + /* -0.5 is to prevent carry/rollover after accumulation */ + /* Could get better accuracy with saturation arithmatic */ + + /* Allocate the table */ + if ((t = (byte *)malloc(ibdinc[it->id])) == NULL) { +#ifdef VERBOSE + printf("malloc imdi interpolation table size %d failed\n",ibdinc[it->id]); +#endif + return NULL; /* Should we signal error ? How ? */ + } + it->size += ibdinc[it->id]; +#ifdef VERBOSE + printf("Allocated grid table = %u bytes, composed of %d dim of res %d entry %d\n",ibdinc[it->id], it->id, gs->itres, ts->im_ts); +#endif /* VERBOSE */ + + /* Get ready to access all the entries in the table */ + p = t; + PH_INIT(phc, it->id, gs->itres) + + /* Create all the interpolation table entry values */ + do { + int ee, ff; + double riv[IXDI]; /* Real input values */ + double rev[IXDO]; /* Real entry values */ + unsigned long iev; + byte *pp; /* Pointer to sub-entry */ + + for (e = 0, p = t; e < it->id; e++) { + riv[e] = ((double)phc[e]) / (gs->itres - 1.0); + p += phc[e] * ibdinc[e]; /* Compute pointer to entry value */ + } + + /* Lookup this verticies value */ + { + double mriv[IXDI]; /* Channel mapped real input values */ + double mrev[IXDO]; /* Channel mapped real entry values */ + for (e = 0; e < it->id; e++) + mriv[it->it_map[e]] = riv[e]; + md_table(cntx, mrev, mriv); + for (e = 0; e < it->od; e++) + rev[e] = mrev[it->im_map[e]]; + } + + /* Create all the output values */ + + /* I'm trying to avoid having to declare the actual entry sized */ + /* variables, since it is difficult dynamically. */ + + /* For all the full entries */ + ff = 0; + pp = p; + for (e = 0; e < ts->im_fn; e++, pp += ts->im_fs) { + /* For all channels within full entry */ + for (ee = 0; ee < ts->im_fv; ee++, ff++) { + double revf = rev[ff]; + if (revf < 0.0) /* Guard against sillies */ + revf = 0.0; + else if (revf > 1.0) + revf = 1.0; + iev = (unsigned long)(revf * vscale + 0.5); + + if (bigend) { + write_entry[vsize](pp + (ts->im_fs - (ee+1) * vsize), iev); + } else { + write_entry[vsize](pp + ee * vsize, iev); + } + } + } + + /* For all the 0 or 1 partial entry */ + for (e = 0; e < ts->im_pn; e++) { + /* For all channels within partial entry */ + for (ee = 0; ee < ts->im_pv; ee++, ff++) { + double revf = rev[ff]; + if (revf < 0.0) /* Guard against sillies */ + revf = 0.0; + else if (revf > 1.0) + revf = 1.0; + iev = (unsigned long)(revf * vscale + 0.5); + + if (bigend) { + write_entry[vsize](pp + (ts->im_ps - (ee+1) * vsize), iev); + } else { + write_entry[vsize](pp + ee * vsize, iev); + } + } + } +#ifdef ASSERTS + if (f != it->od) + fprintf(stderr,"imdi_tab assert: f == it->od\n"); +#endif + + PH_INC(phc) + + } while (!PH_LOOPED(phc)); + + /* Put table into place */ + it->im_table = (void *)t; + } + + /* Setup the simplex table */ + if (ts->sort) { + it->sw_table = (void *)NULL; + + } else { + byte *t, *p; /* Pointer to input table, pointer to total entry */ + int nsplx; /* Total number of simplexes */ + XCOMBO(vcmb, it->id+1, 1 << it->id);/* Simplex dimension id out of cube dimention id */ + int comb[24][IXDI]; /* Parameter[id]->Absolute[id] coordinate index */ + int ps[IXDI+1]; /* Base simplex parameter space counter */ + int pse; /* Base simplex parameter space counter index */ + int idioff; /* Interpolation table diagonal offset value */ + + if (it->id > 4) { + fprintf(stderr,"imdi_tabl: internal failure - trying to create simplex table with di > 4!\n"); + exit(-1); + } + + /* Allocate the table */ + if ((t = (byte *)malloc(sbdinc[it->id])) == NULL) { +#ifdef VERBOSE + printf("malloc imdi simplex table size %d failed\n",sbdinc[it->id]); +#endif + return NULL; /* Should we signal error ? How ? */ + } + it->size += sbdinc[it->id]; +#ifdef VERBOSE + printf("Allocated simplex table = %u bytes, composed of %d dim of res %d entry %d\n",sbdinc[it->id], it->id, gs->stres, ts->sm_ts); +#endif /* VERBOSE */ + + /* Compute the interp table offset to the diagonal vertex */ + for (idioff = 0, e = 0; e < it->id; e++) + idioff += idinc[e]; /* Sum one offset in each dimension */ + + /* Figure out how many simplexes fit into this dimension cube, */ + /* and how to map from the base simplex to each actual simplex. */ + XCB_INIT(vcmb); + for (nsplx = 0; ;) { + int i; + + /* XCOMB generates verticies in order from max to min offest */ + + /* Compute Absolute -> Parameter mapping */ + for (e = 0; e < it->id; e++) { /* For each absolute axis */ + for (i = 0; i < it->id; i++) { /* For each verticy, order large to small */ + if ((vcmb[i] & (1<<e)) != 0 && + (vcmb[i+1] & (1<<e)) == 0) {/* Transition from offset 1 to 0 */ + comb[nsplx][i] = e; + break; + } + } + } + +//printf("~~Verticies = "); +//for (i = 0; i <= it->id; i++) +// printf("%d ",vcmb[i]); +//printf("\n"); + +//printf("~~Parm -> Abs = "); +//for (e = 0; e < it->id; e++) +// printf("%d ",comb[nsplx][e]); +//printf("\n"); + + /* Increment the counter value */ + XCB_INC(vcmb); + nsplx++; + if (XCB_DONE(vcmb)) + break; + } + + /* Now generate the contents of the base simplex, */ + /* and map it to all the symetrical simplexes */ + + /* Init parameter space counter. */ + /* Note that ps[id-1] >= ps[id-2] >= ... >= ps[1] >= ps[0] */ + for (pse = 0; pse < it->id; pse++) + ps[pse] = 0; + ps[pse] = gs->stres-1; + + /* Itterate through the simplex parameter space */ + for (pse = 0; pse < it->id;) { + int qps[IXDI]; /* Quantized parameter values */ + int we[IXDI+1]; /* Baricentric coords/vertex weighting */ + double wvscale = (1 << gs->prec); /* Weighting value scale */ + int sx; /* Simplex */ + +//printf("Param coord ="); +//for (e = it->id-1; e >= 0; e--) { +// printf(" %d",ps[e]); +//} +//printf("\n"); + + for (e = 0; e < it->id; e++) { + /* (Should try wvscale + 0.49999999, or something ?) */ + double tt = (wvscale * (double)ps[e])/((double)gs->stres); + qps[e] = (int)(tt + 0.5); + } + + /* Convert quantized parameter values into weighting values */ + we[it->id] = (1 << gs->prec) - qps[it->id-1]; + for (e = it->id-1; e > 0; e--) + we[e] = qps[e] - qps[e-1]; + we[0] = qps[0]; + +#ifdef ASSERTS + { + int sow = 0; + for (e = it->id; e >= 0; e--) + sow += we[e]; + + if (sow != (1 << gs->prec)) + fprintf(stderr,"imdi_tab assert: sum weights == (1 << gs->prec)\n"); + } +#endif + +//printf("Baricentric coord ="); +//for (e = it->id; e >= 0; e--) { +// printf(" %d",we[e]); +//} +//printf("\n"); + + /* For each simplex, compute the interp. and */ + /* and entry offsets, and write the entry. */ + for (sx = 0; sx < nsplx; sx++ ) { + int v; /* Vertex index */ + byte *pp; /* Pointer to sub-entry */ + unsigned long vofb = 0; /* Vertex offset, base */ + unsigned long vwe; /* Vertex weight */ + + for (e = 0, p = t; e < it->id; e++) { + int ee = comb[sx][e]; /* Absolute coord index */ + p += ps[e] * sbdinc[ee]; /* Pointer to entry */ + } + + /* For each vertex entry */ + for (v = 0, pp = p; v <= it->id; v++) { + unsigned long vof; + if (v == 0) { + vofb = idioff; /* Start at diagonal offset */ + } else { + vofb -= idinc[comb[sx][v-1]];/* Move to next vertex */ + } + vwe = we[v]; /* Weight for this vertex */ + + if (vwe == 0) + vof = 0; /* Use zero offset if weight is zero */ + else + vof = vofb * ts->vo_om; /* Strength reduce kernel scaling */ + + /* Write vwe and vof to entry */ + if (ts->wo_xs) { /* Separate entries */ + write_entry[ts->we_es](pp + ts->we_eo, vwe); + write_entry[ts->vo_es](pp + ts->vo_eo, vof); + pp += ts->wo_es; + } else { /* Combined entries */ + bvt iwo; + + iwo = ((bvt)vwe << ts->vo_ab) | vof; /* Combined weight+vertex offset */ + write_entry[ts->wo_es](pp + ts->wo_eo, iwo); + pp += ts->wo_es; + } + } + + /* Assert vofb == 0 */ +#ifdef ASSERTS + if (vofb != 0) + fprintf(stderr,"imdi_tab assert: vofb == 0\n"); +#endif + } /* Next simplex */ + + /* Increment the parameter coords */ + for (pse = 0; pse < it->id; pse++) { + ps[pse]++; + if (ps[pse] <= ps[pse+1]) + break; /* No carry */ + ps[pse] = 0; + } + } + + /* Put table into place */ + it->sw_table = (void *)t; + } + + /* Last, setup the output tables */ + for (e = 0; e < it->od; e++) { + byte *t, *p; /* Pointer to output table, entry pointer */ + int ne; /* Number of entries */ + int iiv; /* Integer input value */ + double ivr = (double)((1 << gs->prec)-1); /* Input value range */ + double ovr = (double)((1 << ts->ot_bits[e])-1); /* Output value range */ + int osb = (1 << (ts->ot_bits[e]-1)); /* Output offset to signed displacement */ + int ooff = ts->ot_off[e]; /* Output value bit offset */ + + ne = (1 << gs->prec); /* Output of clut is prec bits */ + + /* Allocate the table */ + if ((t = (byte *)malloc(ts->ot_ts * ne)) == NULL) { +#ifdef VERBOSE + printf("malloc imdi output table size %d failed\n",ts->ot_ts * ne); +#endif + return NULL; /* Should we signal error ? How ? */ + } + it->size += ts->ot_ts * ne; +#ifdef VERBOSE + printf("Allocated output table %d size %u = %u * %u\n",e, ts->ot_ts * ne,ts->ot_ts,ne); +#endif /* VERBOSE */ + + /* For each possible output value, compute the entry value */ + for (iiv = 0, p = t; iiv < ne; iiv++, p += ts->ot_ts) { + double riv; /* Real input value, 0.0 - 1.0 */ + double rtv; /* Real transformed value, 0.0 - 1.0 */ + unsigned long iov; /* Integer output value */ + + riv = (double) iiv / ivr; /* Compute floating point */ + { + double civ[IXDO], cov[IXDO]; + for (f = 0; f < it->od; f++) + civ[f] = riv; + output_curves(cntx, cov, civ); /* Lookup the input table transform */ + rtv = cov[it->im_map[e]]; + } + if (rtv < 0.0) /* Guard against sillies */ + rtv = 0.0; + else if (rtv > 1.0) + rtv = 1.0; + iov = (unsigned long)(rtv * ovr + 0.5); /* output value */ + if (gs->out_signed & (1 << e)) /* Treat output as signed */ + iov = (iov & osb) ? iov - osb : iov + osb; /* Convert to signed from offset */ + iov <<= ooff; /* Aligned for output */ + + write_entry[ts->ot_ts](p, iov); /* Write entry */ + } + + /* Put table into place */ + it->out_tables[e] = (void *)t; + } + it->nouttabs = e; + + /* Adjust the check values for output value shift */ + for (e = 0; e < it->od; e++) { + int ooff = ts->ot_off[e]; /* Output value bit offset */ + it->checkv[e] <<= ooff; /* Aligned for output */ + } + + /* Setup the appropriate skip flags, indexed by Output channel */ + it->skipf = 0; + if ((oopt & OOPTS_SKIP) != 0) { + int i; + for (i = 0; i < it->od; i++) { + if (oopt & OOPT(oopts_skip,it->im_map[i])) { /* Skip flag for this output chan */ + it->skipf |= (1 << i); + } + } + } + + /* Fill in some report information */ + it->gres = gs->itres; + if (!ts->sort) { + it->sres = gs->stres; + } else { + it->sres = 0; + } + +#ifdef VERBOSE + printf("imdi_tabl returning OK\n"); +#endif + return it; +} + +/* Free up the data allocated */ +void +imdi_tab_free( +imdi_imp *it +) { + int e; + + for (e = 0; e < it->nintabs; e++) + free(it->in_tables[e]); + + if (it->sw_table != NULL) + free(it->sw_table); + if (it->im_table != NULL) + free(it->im_table); + + for (e = 0; e < it->nouttabs; e++) + free(it->out_tables[e]); + + free(it); + +} + + + + + + + + + + + + + + + |