PTErr_t makeForwardXformMono ( ResponseRecord_p grayTRC, fut_p theFut) { PTErr_t PTErr = KCP_FAILURE; KpInt32_t futReturn, i1; fut_otbldat_p otblDat; double gamma; fut_calcData_t calcData; KpUInt16_t rrpData[2] = { 0, RRECORD_DATA_SIZE -1 }; ResponseRecord_t rrt; KpUInt16_t *pCurveData = NULL; /* compute new table entries */ calcData.chan = 0; /* always uses 1st input chan */ for (i1 = 0; i1 < FWD_MONO_OCHANS; i1++) { if (( ! IS_CHAN(theFut->chan[i1])) || !fut_calc_gtblEx (theFut->chan[i1]->gtbl, fut_grampEx, &calcData) || !fut_calc_otblEx (theFut->chan[i1]->otbl, otblFunc, NULL)) { goto ErrOut0; } } /* get address of the first output table */ futReturn = fut_get_otbl (theFut, 0, &otblDat); if ((futReturn != 1) || (otblDat == (fut_otbldat_p)NULL)) { goto ErrOut0; } if (PARA_TYPE_SIG == grayTRC->TagSig) { pCurveData = (KpUInt16_p) allocBufferPtr (MFV_CURVE_TBL_ENT); /* get memory for curve data */ if (NULL == pCurveData) { return KCP_NO_MEMORY; } makeCurveFromPara (grayTRC->ParaFunction, grayTRC->ParaParams, pCurveData, MFV_CURVE_TBL_ENT); grayTRC->CurveCount = MFV_CURVE_TBL_ENT; grayTRC->CurveData = pCurveData; } /* setup the output table */ switch (grayTRC->CurveCount) { case 0: /* setup the responseRecord struct */ rrt.CurveCount = 2; rrt.CurveData = rrpData; /* make the output table */ PTErr = calcOtblLSN (otblDat, &rrt); break; case 1: gamma = (double)grayTRC->CurveData[0] / SCALEDOT8; if (gamma <= 0.0) { goto ErrOut0; } /* make the output table */ PTErr = calcOtblLS1 (otblDat, gamma); break; default: /* make the output table */ makeMonotonic (grayTRC->CurveCount, grayTRC->CurveData); PTErr = calcOtblLSN (otblDat, grayTRC); } GetOut: if (NULL != pCurveData) { freeBufferPtr (pCurveData); } return PTErr; ErrOut0: PTErr = KCP_SYSERR_0; goto GetOut; }
/*------------------------------------------------------------------- * init_xfer -- initialize the transfer tables by transferring coarse * control points from an ICC ResponseRecord * and interpolating the fine tables from them; * returns +1 for success, -1 for failure to * allocate memory for coarse table *------------------------------------------------------------------- */ PTErr_t init_xfer ( xfer_p xferp, ResponseRecord_p rrp) { PTErr_t PTErr = KCP_SUCCESS; double val; /* input variables */ KpInt32_t numcoarse; /* number of input control points */ double_p coarse[2]; /* storage for control points */ KpInt32_t i; /* control-point index */ KpInt32_t hint; KpUInt16_t *pCurveData = NULL; /* Verify inputs: */ if (xferp == (xfer_p)NULL) return KCP_SYSERR_0; if (rrp == (ResponseRecord_p)NULL) return KCP_SYSERR_0; 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 < 2) { PTErr = KCP_SYSERR_0; goto ErrOut; } if (rrp->CurveData == (KpUInt16_p)NULL) { PTErr = KCP_SYSERR_0; goto ErrOut; } /* Allocate space for coarse tables: */ numcoarse = rrp->CurveCount - 1; /* skip zero entry to avoid infinity in logarithm */ coarse[0] = (double_p)ALLOC (numcoarse, sizeof(double)); if (coarse[0] == NULL) { PTErr = KCP_NO_MEMORY; goto ErrOut; } coarse[1] = (double_p)ALLOC (numcoarse, sizeof(double)); if (coarse[1] == NULL) { DALLOC (coarse[0]); /* release storage */ PTErr = KCP_NO_MEMORY; goto ErrOut; } /* Build coarse tables from ResponseRecord: */ for (i = 0; i < numcoarse; i++) { val = (double)(i + 1) / (double)numcoarse; /* skip zero to avoid infinite log */ coarse[0][i] = -log10 (val); val = (double)rrp->CurveData[i + 1] / SCALEDOT16; val = MAX (val, 1.0e-12); /* clip to avoid infinite log */ coarse[1][i] = -log10 (val); } /* Build fine tables by interpolating in coarse tables: */ hint = 1; for (i = 0; i < NUMFINE; i++) /* spaced code values */ { double code; code = (double)i * 2.4 / (double)(NUMFINE - 1); /* equally spaced in [0, 2.4] */ xferp->nonlinear[i] = code; xferp->linear[i] = f4l (code, coarse[0], coarse[1], numcoarse, &hint); } /* Delete coarse tables: */ DALLOC (coarse[0]); DALLOC (coarse[1]); ErrOut: if (NULL != pCurveData) { freeBufferPtr (pCurveData); } return PTErr; }
/*--------------------------------------------------------------------------- * 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; }