/* fut_size_gtbl returns the size in bytes of a grid table */ static KpInt32_t fut_size_gtbl ( fut_gtbl_p gtbl) { if (( ! IS_GTBL (gtbl)) || (gtbl->tbl == NULL)) return (0); return (((KpInt32_t)sizeof (KpInt32_t)*5) + ((KpInt32_t)sizeof (KpInt16_t)*FUT_NCHAN) + gtbl->tbl_size); }
/* fut_free_gtbl_p This function is passed a fut_gtbl_t pointer and handle. If the ref count is zero, the table and the fut_gtbl_t is freed. Otherwise the ref count is decremented and the lock state of the fut_gtbl_t is returned to it's state on entry. */ static void fut_free_gtbl_p ( fut_gtbl_p gtblP, KpHandle_t gtblHdl) { fut_gtbl_p gtbl = gtblP; if (gtblHdl == NULL) { return; } if (gtbl == NULL) { /* gtbl is unlocked on entry */ gtbl = lockBuffer(gtblHdl); } if (IS_GTBL(gtbl)) { if (gtbl->ref == 0) { fut_free_gtbl(gtbl); /* last reference being freed */ } else { if (gtbl->ref > 0) { /* still other references, leave in original lock state */ gtbl->ref--; if (gtblP == NULL) { unlockBuffer(gtblHdl); } } } } }
KpInt32_t fut_calc_gtblEx ( fut_gtbl_p gtbl, fut_gfunc_t gfun, fut_calcData_p data) { KpInt32_t index, n[FUT_NICHAN], i[FUT_NICHAN], mftData; double norm[FUT_NICHAN], cList[FUT_NICHAN], val, mftMaxData = MF2_TBL_MAXVAL; mf2_tbldat_p grid; if ( ! IS_GTBL(gtbl) ) { return (0); } if (gfun != NULL) { /* set up grid size in each dimension */ for (index = 0; index < FUT_NICHAN; index++) { n[index] = gtbl->size[index]; if (n[index] == 1) { norm[index] = 0.0; } else { norm[index] = 1.0 / (double) (n[index] -1); } } gtbl->id = fut_unique_id(); /* new table data, new id */ /* construct function of 1 to 8 input variables */ grid = gtbl->refTbl; GCLOOP(0) GCLOOP(1) GCLOOP(2) GCLOOP(3) GCLOOP(4) GCLOOP(5) GCLOOP(6) GCLOOP(7) val = (*gfun)(cList, data); MFT_QUANT(val, mftData) *grid++ = (mf2_tbldat_t)mftData; GCLEND GCLEND GCLEND GCLEND GCLEND GCLEND GCLEND GCLEND } return (1); }
/* fut_copy_gtbl makes an exact copy of an existing fut_gtbl_t */ fut_gtbl_p fut_copy_gtbl (fut_gtbl_p gtbl) { fut_gtbl_p new_gtbl; KpInt32_t gsize; KpHandle_t h; /* check for valid gtbl */ if ( ! IS_GTBL(gtbl) ) { return (FUT_NULL_GTBL); } new_gtbl = fut_alloc_gtbl (); /* allocate the new gtbl structure */ if ( new_gtbl == FUT_NULL_GTBL ) { DIAG("fut_copy_gtbl: can't alloc grid table struct.\n", 0); return (FUT_NULL_GTBL); } h = new_gtbl->handle; /* save handle before copying over old gtbl */ *new_gtbl = *gtbl; /* copy entire struct except reference count */ new_gtbl->handle = h; new_gtbl->ref = 0; /* first reference */ if (gtbl->tbl != NULL) { /* copy fixed gtbl data */ gsize = gtbl->tbl_size / (KpInt32_t)sizeof(fut_gtbldat_t); new_gtbl->tbl = fut_alloc_gtbldat (new_gtbl); if ( new_gtbl->tbl == NULL ) { DIAG("fut_copy_gtbl: can't alloc grid table array.\n", 0); goto ErrOut; } new_gtbl->tblHandle = getHandleFromPtr((KpGenericPtr_t)new_gtbl->tbl); /* copy the table entries */ KpMemCpy (new_gtbl->tbl, gtbl->tbl, gtbl->tbl_size); } if (gtbl->refTbl != NULL) { /* copy reference gtbl data */ new_gtbl->refTbl = fut_alloc_gmftdat (new_gtbl); if (new_gtbl->refTbl == NULL ) { DIAG("fut_copy_gtbl: can't alloc ref grid table array.\n", 0); goto ErrOut; } /* copy the table entries */ KpMemCpy (new_gtbl->refTbl, gtbl->refTbl, gtbl->tbl_size); } return (new_gtbl); ErrOut: fut_free_gtbl (new_gtbl); return (FUT_NULL_GTBL); }
void fut_free_gmftdat ( fut_gtbl_p gtbl, fut_freeMode_t mode) { if (IS_GTBL(gtbl)) { if ((mode == freeTable) || ((mode == freeData) && (gtbl->tbl != NULL))) { freeBuffer (gtbl->refTblHandle); gtbl->refTbl = NULL; gtbl->refTblHandle = NULL; } } }
void fut_free_gtbl (fut_gtbl_p gtbl) { if ( ! IS_GTBL(gtbl)) { /* defined? */ return; } if (gtbl->ref != 0) { /* last reference? */ gtbl->ref--; } else { fut_free_gmftdat (gtbl, freeTable); /* free the data */ fut_free_gtbldat (gtbl, freeTable); gtbl->magic = 0; freeBufferPtr ((KpGenericPtr_t)gtbl); } }
/* fut_new_chan allocates and initializes a fut_chan_t data structure. * If a required input table is missing, a ramp of the proper grid size * will be created. If a supplied itbl is not required, it will not be * inserted into the channel's private itbl list. All tables which are * actually used are copied and so the caller is responsible for * freeing the passed tables if necessary. * * If VARARGS is used, the list of input tables may be relaced by a * single array of fut_itbl_t pointers. This array must then be followed * by a fut_gtbl_p and a fut_otbl_p. */ fut_chan_p fut_new_chan ( KpInt32_t iomask, fut_itbl_p FAR* itbls, fut_gtbl_p gtbl, fut_otbl_p otbl) { fut_itbl_p itbl[FUT_NCHAN]; fut_chan_p chan; KpInt32_t imask, i, tIndex; /* get input mask */ imask = (KpInt32_t)FUT_IMASK(iomask); /* get args specified by imask */ for ( i=0, tIndex = 0; i<FUT_NCHAN; i++ ) { itbl[i] = ((imask & FUT_BIT(i)) && (itbls != NULL)) ? itbls[tIndex++] : NULL; } /* allocate and clear the fut_chan_t structure */ chan = fut_alloc_chan (); if ( ! IS_CHAN(chan)) { return (NULL); } /* check for valid grid and output tables */ if (( ! IS_GTBL(gtbl)) || ((otbl != NULL) && ( ! IS_OTBL(otbl))) ) { DIAG("fut_new_chan: invalid grid or output table.\n", 0); fut_free_chan (chan); return (NULL); } /* get required input channels from gtbl */ chan->imask = fut_gtbl_imask(gtbl); /* insert the required input tables */ for ( i=0; i<FUT_NICHAN; i++ ) { if ( (chan->imask & FUT_BIT(i)) == 0 ) continue; if ( itbl[i] == FUT_NULL_ITBL ) { chan->itbl[i] = fut_new_itblEx (KCP_REF_TABLES, KCP_FIXED_RANGE, gtbl->size[i], fut_irampEx, NULL); if ( chan->itbl[i] == NULL) { DIAG("fut_new_chan: can't create itbl.\n",0); fut_free_chan (chan); return (NULL); } chan->itblHandle[i] = chan->itbl[i]->handle; } else { if ( ! IS_ITBL (itbl[i])) { DIAG("fut_new_chan: invalid input table.\n", 0); fut_free_chan (chan); return (NULL); } else { if ( itbl[i]->size != gtbl->size[i] ) { DIAG("fut_new_chan: gtbl-itbl size mismatch.\n", 0); fut_free_chan (chan); return (NULL); } else { chan->itbl[i] = fut_share_itbl(itbl[i]); /* share the input table */ chan->itblHandle[i] = chan->itbl[i]->handle; } } } } /* insert grid and output tables */ chan->gtbl = fut_share_gtbl (gtbl); chan->gtblHandle = (IS_GTBL(chan->gtbl)) ? chan->gtbl->handle : FUT_NULL_HANDLE; if (IS_OTBL(otbl)) { chan->otbl = fut_share_otbl (otbl); } else { chan->otbl = fut_alloc_otbl(); } chan->otblHandle = (IS_OTBL(chan->otbl)) ? chan->otbl->handle : FUT_NULL_HANDLE; return (chan); }
/*--------------------------------------------------------------------------- * makeInverseXformFromMatrix -- make a fut of given gridsize from given * matrix data for inverse transform (XYZ -> RGB); return status code *--------------------------------------------------------------------------- */ PTErr_t makeInverseXformFromMatrix (LPMATRIXDATA mdata, KpUInt32_t interpMode, KpInt32_p dim, fut_p theFut) { PTErr_t PTErr = KCP_SUCCESS; ResponseRecord_p rrp; KpInt32_t i; fut_chan_p theChan; fut_gtbl_p theGtbl; fut_otbl_p theOtbl; mf2_tbldat_p gtblDat[3], otblDat, prevOtblDat; KpUInt16_t prevGamma = 0, thisGamma; double fwdgamma, one[3]; double offset[3] = {1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0}; KpUInt16_t *pCurveData = NULL; for (i = 0; i < 3; i++) { if (!IS_CHAN(theChan = theFut->chan[i]) || !IS_GTBL(theGtbl = theChan->gtbl) || ((gtblDat[i] = theGtbl->refTbl) == NULL) /* Get grid tables */ || !IS_OTBL(theOtbl = theChan->otbl) || ((otblDat = theOtbl->refTbl) == NULL)) { /* Get output table */ return KCP_INCON_PT; } if (theOtbl->refTblEntries != FUT_OUTTBL_ENT) return KCP_INCON_PT; /* Get ResponseRecord: */ rrp = mdata->outResponse[i]; if (NULL == rrp) { break; /* must only have output tables */ } if (PARA_TYPE_SIG == rrp->TagSig) { pCurveData = (KpUInt16_p) allocBufferPtr (MFV_CURVE_TBL_ENT*sizeof(KpUInt16_t)); /* get memory for curve data */ if (NULL == pCurveData) { return KCP_NO_MEMORY; } makeCurveFromPara (rrp->ParaFunction, rrp->ParaParams, pCurveData, MFV_CURVE_TBL_ENT); rrp->CurveCount = MFV_CURVE_TBL_ENT; rrp->CurveData = pCurveData; } if ((rrp->CurveCount > 0) && (rrp->CurveData == (KpUInt16_p)NULL)) { PTErr = KCP_INCON_PT; goto ErrOut; } /* Recompute output table: */ switch (rrp->CurveCount) { case 0: /* linear response, with clipping */ calcOtbl0 (otblDat); break; case 1: /* power law */ thisGamma = rrp->CurveData[0]; if (prevGamma == thisGamma) { /* same gamma, just copy table */ memcpy (otblDat, prevOtblDat, sizeof (*otblDat) * FUT_OUTTBL_ENT); } else { prevGamma = thisGamma; prevOtblDat = otblDat; fwdgamma = (double)thisGamma / SCALEDOT8; if (fwdgamma <= 0.0) { PTErr = KCP_INCON_PT; goto ErrOut; } calcOtbl1 (otblDat, fwdgamma); } break; default: /* look-up table of arbitrary length */ makeInverseMonotonic (rrp->CurveCount, rrp->CurveData); if (rrp->CurveCount == theOtbl->refTblEntries) { /* ready-to-use look-up table */ memcpy (otblDat, rrp->CurveData, sizeof (*otblDat) * rrp->CurveCount); } else { PTErr = calcOtblN (otblDat, rrp, interpMode); if (PTErr != KCP_SUCCESS) { PTErr = KCP_INCON_PT; goto ErrOut; } } break; } } /* Compute inverse matrix (XYZ -> RGB): */ one[0] = one[1] = one[2] = 1.0; /* arbitrary vector */ /* replaces matrix with inverse */ if (solvemat (3, mdata->matrix, one) != 0) { PTErr = KCP_INCON_PT; goto ErrOut; } /* Rescale given matrix by factor of 3 for extended range: */ for (i = 0; i < 3; i++) { KpInt32_t j; for (j = 0; j < 3; j++) { mdata->matrix[i][j] /= 3.0; } } /* Replace grid tables: */ calcGtbl3 (gtblDat, dim, mdata->matrix, offset); /* with offset */ ErrOut: if (NULL != pCurveData) { freeBufferPtr (pCurveData); } return PTErr; }