Esempio n. 1
0
/* fut_add_chan inserts a new output channel into a fut.
 * Unlike itbls, otbls, and gtbls, the channel structure is not sharable
 * and so the caller must not free the chan after this call.	(If the
 * passed channel structure needs to be saved, use fut_copy_chan).
 * The iomask in this case simply tells which output channel is being
 * added, and if this channel already exists, an error (0) is returned.
 *
 * fut_add_chan is intended to be used in conjunction with fut_new_chan
 * to construct futs with independent input tables.	It does not update
 * the list of common input tables as does fut_new and fut_defchan and
 * should not be mixed with calls to fut_defchan.
 */
KpInt32_t
	fut_add_chan (fut_p	fut, KpInt32_t iomask, fut_chan_p chan)
{
	KpInt32_t		ochan;

	if ( ! IS_FUT(fut) || (chan != FUT_NULL_CHAN && ! IS_CHAN(chan)) ) {
		return (0);
	}

					/* get output channel no. */
	ochan = FUT_CHAN ((KpInt32_t)FUT_OMASK(iomask));

					/* prohibit redefinition of channel */
	if ( ochan >= FUT_NOCHAN || fut->chan[ochan] != NULL)
		return (0);
					/* insert channel into fut */
	fut->chan[ochan] = chan;
	fut->chanHandle[ochan] = (IS_CHAN(fut->chan[ochan])) ?
								fut->chan[ochan]->handle : FUT_NULL_HANDLE;

					/* update iomasks */
	if ( IS_CHAN(chan) ) {
		fut->iomask.out |= FUT_BIT(ochan);
		fut->iomask.in |= chan->imask;
	}

	return (1);
}
Esempio n. 2
0
/* fut_free_chan_list_p
		For each channel, This functions frees all input tables, 
		the output table and the grid table.	It then frees the
		actual fut_chan_t memory.
*/
static void
	fut_free_chan_list_p (	fut_chan_p FAR *	chan_list,
							KpHandle_t FAR *	chanHdl_list)
{
KpInt32_t	i;
fut_chan_p	chan;

	if ( (chan_list == NULL) || ( chanHdl_list == NULL)	)
		return;


	for ( i=0; i<FUT_NOCHAN; i++ ) {
		chan = chan_list[i];
		if (chan == NULL) {		/* chan is unlocked on entry */
			chan = lockBuffer(chanHdl_list[i]);
		}
		
		if (IS_CHAN(chan)) {
			fut_free_itbl_list_p (chan->itbl, chan->itblHandle);	/* free input tables */

			fut_free_otbl_p (chan->otbl, chan->otblHandle);		/* free output table */

			fut_free_gtbl_p (chan->gtbl, chan->gtblHandle);		/* free grid table */

			/* free fut_chan_t structure itself */
			chan->magic = 0;
			freeBufferPtr ((KpGenericPtr_t)chan);
			chan_list[i] = FUT_NULL_CHAN;
		}
	}
}
Esempio n. 3
0
////////////////////////////////////////////////////////////
// HANDLE EVENT FROM RAW MIDI NOTE
// Note on has velocity > 0
void gate_midi_note(byte chan, byte note, byte vel) 
{
	// for each gate output
	for(byte which_gate=0; which_gate<GATE_MAX; ++which_gate) {
		GATE_OUT *pgate = &l_gate[which_gate];
		GATE_OUT_CFG *pcfg = &l_gate_cfg[which_gate];
		
		// does this gate respond to midi note?
		if(pcfg->event.mode != GATE_MIDI_NOTE)
			continue;			
		// does the MIDI channel match?
		if(!IS_CHAN(pcfg->note.chan, chan))
			continue;			
		// Does the note match?
		if(!IS_NOTE_MATCH(pcfg->note.note, pcfg->note.note_max, note))
			continue;			
		// is this a note off or note on with velocity above threshold?
		if(vel && vel < pcfg->note.vel_min) {			
			continue;
		}		
		
		// trigger (for note on) or untrigger (for note off)
		trigger(pgate, pcfg, which_gate, !!vel, false);
	}			
}
Esempio n. 4
0
static KpInt32_t
	fut_size_chan (	fut_chan_p	chan,
					chan_hdr_p	chanio)
{
KpInt32_t size = 0;
KpInt32_t	i1;

	if ( ! IS_CHAN (chan) )
		return (0);

/* add up size of the input tables */
	for ( i1=0; i1<FUT_NICHAN; i1++ ) {
		if ( chanio->icode[i1] == FUTIO_UNIQUE )
			size += fut_size_itbl (chan->itbl[i1]);
	}

/* add up size of the output table */
	if ( chanio->ocode == FUTIO_UNIQUE ) {
		size += fut_size_otbl (chan->otbl);
	}

/* add up size of the grid table */
	if ( chanio->gcode == FUTIO_UNIQUE ) {
		size += fut_size_gtbl (chan->gtbl);
	}

	return size;
}
Esempio n. 5
0
void
	fut_free_chan (fut_chan_p chan)
{
	if ( ! IS_CHAN(chan) )	/* check if defined */
		return;

	fut_free_itbl_list (chan->itbl);	/* free input tables */

	fut_free_otbl (chan->otbl);		/* free output table */

	fut_free_gtbl (chan->gtbl);		/* free grid table */

				/* free fut_chan_t structure itself */
	chan->magic = 0;
	freeBufferPtr ((KpGenericPtr_t)chan);

}
Esempio n. 6
0
void
	fut_free_mftdat		(fut_p	fut)
{
KpInt32_t	i;
fut_chan_p	chan;

	if (IS_FUT(fut)) {
		fut_free_itbldat_list (&fut->itbl[0], FUT_MFTDATA);
		
		for ( i=0; i<FUT_NOCHAN; i++ ) {
			chan = fut->chan[i];
			if (IS_CHAN(chan)) {
				fut_free_itbldat_list (&chan->itbl[0], FUT_MFTDATA);
				fut_free_gmftdat (chan->gtbl, freeData);
				fut_free_omftdat (chan->otbl, freeData);
			}
		}
	}
}
Esempio n. 7
0
////////////////////////////////////////////////////////////
// HANDLE EVENT FROM RAW MIDI CC
void gate_midi_cc(byte chan, byte cc, byte value) 
{
	// for each gate output
	for(byte which_gate=0; which_gate<GATE_MAX; ++which_gate) {
		GATE_OUT *pgate = &l_gate[which_gate];
		GATE_OUT_CFG *pcfg = &l_gate_cfg[which_gate];
		
		// does this gate respond to CC?
		if(pcfg->event.mode != GATE_MIDI_CC && 
			pcfg->event.mode != GATE_MIDI_CC_NEG)
			continue;
		
		// is this the correct CC?	
		if(cc != pcfg->cc.cc) {
			continue;
		}		
		// does the MIDI channel match?
		if(!IS_CHAN(pcfg->cc.chan, chan))
			continue;

				
		// has the value just gone above threshold?
		if(value >= pcfg->cc.threshold &&
			( pgate->value < pcfg->cc.threshold || 
				pgate->value == NO_VALUE)) {
			
			// trigger gate
			trigger(pgate, pcfg, which_gate, !(pcfg->event.mode == GATE_MIDI_CC_NEG), false);
			pgate->value = value;		
		}
		// has the value just gone below threshold?
		else if(value < pcfg->cc.threshold &&
			( pgate->value >= pcfg->cc.threshold || 
				pgate->value == NO_VALUE)) {
			
			// untrigger gate
			trigger(pgate, pcfg, which_gate, (pcfg->event.mode == GATE_MIDI_CC_NEG), false);
			pgate->value = value;		
		}
	}			
}
Esempio n. 8
0
/* fut_comp_chan_ilut composes (in place) the input tables of a
 * fut output channel with the look-up tables specified in the
 * list, luts.  The original and new input tables from the
 * parent fut must be passed in order to preserve the sharing
 * of input tables.
 */
static KpInt32_t
	fut_comp_chan_ilut (fut_chan_p		chan,
						KpChar_p FAR*	luts,
						fut_itbl_p FAR*	orig_itbls,
						fut_itbl_p FAR*	new_itbls,
						KpInt32_t		is_12bits)
{
KpInt32_t	i;
fut_itbl_p	new_itbl;

	if ( ! IS_CHAN(chan) ) {
		return (0);
	}

	/* check each itbl to see if must be computed or shared */
	for ( i=0; i<FUT_NICHAN; i++ ) {
		if ((luts[i] == NULL) || (chan->itbl[i] == NULL))
			continue;

		if ((orig_itbls != NULL) && (chan->itbl[i] == orig_itbls[i])) {
			new_itbl = fut_share_itbl(new_itbls[i]);
		}
		else {
			new_itbl = fut_comp_itbl_ilut (chan->itbl[i], luts[i], is_12bits);
		}

		if (new_itbl == FUT_NULL_ITBL) {
			return (0);
		}

		/* replace with the new composed or shared itbl */
		fut_free_itbl (chan->itbl[i]);
		chan->itbl[i] = new_itbl;
	}

	return (1);
}
Esempio n. 9
0
/* check the input and output data class of a PT
 * if a color space is known and the data class is not known,
 * set the data class to correspond to the color space
 */
void
	checkDataClass (PTRefNum_t	PTRefNum)
{
KpInt32_t		i1;
KpHandle_t		PTData;
fut_p			fut;
fut_chan_p		chan;
fut_otbl_p		otbl;
PTDataClass_t	iDataClass, oDataClass;

	iDataClass = getPTDataClass (PTRefNum, KCM_IN_SPACE);
	oDataClass = getPTDataClass (PTRefNum, KCM_OUT_SPACE);

	PTData = getPTData (PTRefNum);
	fut = fut_lock_fut (PTData);
	if ( ! IS_FUT(fut)) return;		/* bummer */

	checkInDataClass (iDataClass, fut->itbl);	/* check the data class of each shared input table */

	for (i1 = 0; i1 < FUT_NOCHAN; i1++) {
		chan = fut->chan[i1];

		if (IS_CHAN(chan)) {
			checkInDataClass (iDataClass, chan->itbl);	/* check the data class of each input table */

			if (oDataClass != KCP_UNKNOWN) {	/* check the data class of each output table */
				otbl = chan->otbl;
				if ((IS_OTBL(otbl)) && (otbl->dataClass == KCP_UNKNOWN)) {
					otbl->dataClass = oDataClass;
				}
			}
		}
	}
	
	fut_unlock_fut (fut);
}
Esempio n. 10
0
/* 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);
}
Esempio n. 11
0
/* fut_copy_chan makes a copy of an existing fut_chan_t structure.
 */
fut_chan_p
	fut_copy_chan (fut_chan_p chan)
{
fut_chan_p	new_chan;
KpInt32_t		i;
KpHandle_t		h;

	if ( ! IS_CHAN(chan) ) {
		return (FUT_NULL_CHAN);
	}

	new_chan = fut_alloc_chan ();
	if ( new_chan == FUT_NULL_CHAN ) {
		return (FUT_NULL_CHAN);
	}

				/* save handle before copying over old fut */
	h = new_chan->handle;

				/* copy over to new structure */
	*new_chan = *chan;

				/* move handle back to new structure */
	new_chan->handle = h;

	/* copy itbls
	 * if an itbl is shared, share it with the itbl in the new fut
	 */
	for ( i=0; i<FUT_NICHAN; i++ ) {
		new_chan->itbl[i] = (IS_SHARED (chan->itbl[i])) ?
							fut_share_itbl (chan->itbl[i]) : fut_copy_itbl (chan->itbl[i]);
		new_chan->itblHandle[i] = getHandleFromPtr((KpGenericPtr_t)new_chan->itbl[i]);
	}

					/* copy gtbl */
	new_chan->gtbl = fut_copy_gtbl (chan->gtbl);
	new_chan->gtblHandle =  getHandleFromPtr((KpGenericPtr_t)new_chan->gtbl);

					/* copy otbl */
	new_chan->otbl = (IS_SHARED(chan->otbl)) ?
						fut_share_otbl (chan->otbl) : fut_copy_otbl (chan->otbl);
	new_chan->otblHandle = getHandleFromPtr((KpGenericPtr_t)new_chan->otbl);

					/* check for successful copies */
	for ( i=0; i<FUT_NICHAN; i++ ) {
		if ( new_chan->itbl[i] == 0 && chan->itbl[i] != 0 ) {
			goto ErrOut;
		}
	}

	if ( (new_chan->otbl == 0 && chan->otbl != 0) ||
	     (new_chan->gtbl == 0 && chan->gtbl != 0) ) {
		goto ErrOut;
	}

	return (new_chan);
	

ErrOut:
	fut_free_chan (new_chan);
	return (FUT_NULL_CHAN);
}
Esempio n. 12
0
void
	evalTh1gen (	imagePtr_p	inp,
					KpInt32_p	inStride,
					KpUInt32_t	dataTypeI,
					imagePtr_p	outp,
					KpInt32_p	outStride,
					KpUInt32_t	dataTypeO,
					KpInt32_t	n,
					PTTable_p	PTTableP)
{
imagePtr_t		inData[FUT_NICHAN], outData[FUT_NOCHAN];
KpInt32_t		inStrideL[FUT_NICHAN], outStrideL[FUT_NOCHAN];
KpInt32_t		i1, separableFut, numInputs, numOutputs, gDimSize[FUT_NOCHAN], oTblEntries[FUT_NOCHAN];
division_t		iIndexFactor[FUT_NICHAN], gIndexFactor[FUT_NICHAN], oIndexFactor[FUT_NOCHAN];
KpInt32_t		oDataShift, oDataRound, oDataFactor, dataMax, oDataBits;
fut_p			fut;
fut_itbl_p		iTbl[FUT_NICHAN], theITbl;
fut_chan_p		chan[FUT_NOCHAN], theChan;
mf2_tbldat_p	gTbl[FUT_NOCHAN], oTbl[FUT_NOCHAN];
KpInt32_p		BoseSort[FUT_NICHAN] = {BoseSort1, BoseSort2, BoseSort3, BoseSort4, BoseSort5, BoseSort6, BoseSort7, BoseSort8};
mf2_tbldat_t	identityTable[2] = {0, MF2_TBL_MAXVAL};

	fut = PTTableP->dataP;

	separableFut = fut_is_separable (fut);		/* check for separable (linearization) fut */

	/* set up input table stuff */
	switch (dataTypeI) {
	case KCM_UBYTE:
		dataMax = (1 << 8) -1;
		break;

	case KCM_USHORT_12:
		dataMax = (1 << 12) -1;
		break;

	case KCM_USHORT:
		dataMax = (1 << 16) -1;
		break;
		
	default:
		dataMax = 1;
	}

	for (i1 = 0, numInputs = 0; i1 < FUT_NICHAN; i1++) {
		if (inp[i1].p8 != NULL) {
			inData[numInputs].p8 = inp[i1].p8;	/* copy addresses - do not change supplied lists! */
			inStrideL[numInputs] = inStride[i1];

			theITbl = fut->itbl[i1];
			if ( ! IS_ITBL(theITbl)) {
				return;
			}

			iTbl[numInputs] = theITbl;					/* collect the input tables */

			/* set up interpolation into input table */
			doDivide (theITbl->refTblEntries -1, dataMax, iIndexFactor[numInputs]);	/* set up interpolation into input table */

			/* set up interpolation into grid table */
			gDimSize[i1] = theITbl->size;	/* save in case of separable fut */
			doDivide (gDimSize[i1] -1, MF2_TBL_MAXVAL, gIndexFactor[numInputs]);	/* set up interpolation into input table */
			
			numInputs++;
		}
	}

	/* set up grid and output table stuff */
	for (i1 = 0, numOutputs = 0; i1 < FUT_NOCHAN; i1++) {
		if (outp[i1].p8 != NULL) {
			fut_otbl_p	theOTbl;

			outData[numOutputs].p8 = outp[i1].p8;	/* copy addresses - do not update supplied lists! */
			outStrideL[numOutputs] = outStride[i1];

			theChan = fut->chan[i1];
			if ( ! IS_CHAN(theChan)) {
				return;
			}

			chan[numOutputs] = theChan;

			gTbl[numOutputs] = theChan->gtbl->refTbl;	/* get the grid */

			theOTbl = theChan->otbl;		/* set up interpolation into output table */
			if ( ! IS_OTBL(theOTbl) || ((oTbl[numOutputs] = theOTbl->refTbl) == NULL)) {
				oTbl[numOutputs] = identityTable;
				oTblEntries[numOutputs] = 2;
			}
			else {
				oTblEntries[numOutputs] = theOTbl->refTblEntries;
			}

			doDivide (oTblEntries[numOutputs] -1, MF2_TBL_MAXVAL, oIndexFactor[numOutputs]);	/* set up interpolation into input table */

			numOutputs++;
		}
	}
	
	/* set up output data scaling */
	switch (dataTypeO) {
	case KCM_UBYTE:
		oDataBits = 8;
		break;

	case KCM_USHORT_12:
		oDataBits = 12;
		break;

	case KCM_USHORT:
		oDataBits = 16;
		break;
		
	default:
		dataMax = 1;
	}

	dataMax = (1 << oDataBits) -1;
	oDataShift = 32 -1 - oDataBits;
	oDataFactor = (dataMax << oDataShift) / MF2_TBL_MAXVAL;
	oDataRound = (1 << (oDataShift -1)) -1;


	/* all set up; evaluate each pixel */
	for (i1 = 0; i1 < n; i1++) {
		KpInt32_t	cell, i2, index, dimSize, numCompares, hVert[FUT_NICHAN];
		KpInt32_t	sPosition, iTableData[FUT_NICHAN], hFrac[FUT_NICHAN];
		KpInt32_p	BoseSortP;

		for (i2 = 0, cell = 0; i2 < numInputs; i2++) {
			KpInt32_t	srcData, interpData;

			if (dataTypeI == KCM_UBYTE) {
				srcData = (KpInt32_t) (*inData[i2].p8); 	/* get 8 bit input data */
			}
			else {
				srcData = (KpInt32_t) (*inData[i2].p16); 	/* get 12/16 bit input data */
			}
						
			inData[i2].p8 += inStrideL[i2];

			/* pass source image data through the input table */
			theITbl = iTbl[i2];
			interpData = interp1DTable (theITbl->refTbl, theITbl->refTblEntries, srcData, iIndexFactor[i2]);
			iTableData[i2] = interpData;	/* save in case of separable fut */

			doMultiply (interpData, gIndexFactor[i2], sPosition);	/* calculate the input table position */
			index = sPosition >> EVAL_FRACBITS;

			dimSize = theITbl->size;					/* size of this dimension */

			if (index < dimSize -1) {
				hFrac[i2] = sPosition & ((1 << EVAL_FRACBITS) -1);	/* get grid interpolant */
			}
			else {
				hFrac[i2] = (1 << EVAL_FRACBITS) -1;
				index--;
			}

			hVert[i2] = dimSize;		/* save for offset calcs */
			cell *= dimSize;			/* build cell index */
			cell += index;				/* add in this index */
		}

		/* build offsets for each dimension */
		index = 2;
		for (i2 = numInputs-1; i2 >= 0; i2--) {
			dimSize = hVert[i2];
			hVert[i2] = index;
			index *= dimSize;
		}

		/* find the hyperhedron in which the interpolation point is located */
		BoseSortP = BoseSort[numInputs -1];
		numCompares = *BoseSortP++;		/* first element is # of compares */
		
		for (i2 = 0; i2 < numCompares; i2++) {
			KpInt32_t	tmpI, index1, index2;

			index1 = *BoseSortP++;
			index2 = *BoseSortP++;
			
			/* sort into largest to smallest based upon interpolants */
			tmpI = hFrac[index1];
			if (tmpI < hFrac[index2]) {
				hFrac[index1] = hFrac[index2];	/* swap interpolants */
				hFrac[index2] = tmpI;

				tmpI = hVert[index1];			/* swap vertices */
				hVert[index1] = hVert[index2];
				hVert[index2] = tmpI;
			}
		}

		/* evaluate each output channel */
		for (i2 = 0; i2 < numOutputs; i2++) {
			KpInt32_t	i3, tResult, oTableData, previousVertex, thisVertex;
			KpUInt8_p	vertexP;

			if (separableFut == 1) {
				tResult = interp1DTable (gTbl[i2], gDimSize[i2], iTableData[i2], gIndexFactor[i2]);
			}
			else {		/* hyperhedral interpolation */		
				vertexP = (KpUInt8_p)(gTbl[i2] + cell);

				previousVertex = (KpInt32_t) *(mf2_tbldat_p)(vertexP);
				tResult = previousVertex << (EVAL_FRACBITS - EVAL_EXTENDED_BITS);

				for (i3 = 0; i3 < numInputs; i3++) {
					vertexP += hVert[i3];
					thisVertex = (KpInt32_t) *(mf2_tbldat_p)(vertexP);

					interpolateDelta (previousVertex, thisVertex, hFrac[i3], previousVertex)
					tResult += previousVertex;

					previousVertex = thisVertex;
				}

				tResult += ROUND_VALUE(EVAL_FRACBITS - EVAL_EXTENDED_BITS);
				KCP_SHIFT_RIGHT(tResult, tResult, EVAL_FRACBITS - EVAL_EXTENDED_BITS);
			}

			/* output table lookup */
			oTableData = interp1DTable (oTbl[i2], oTblEntries[i2], tResult, oIndexFactor[i2]);
			oTableData *= oDataFactor;		/* convert to dest size */
			oTableData += oDataRound;		/* round */
			oTableData >>= oDataShift;		/* remove fractional bits */

			if (dataTypeO == KCM_UBYTE) {
				*outData[i2].p8 = (KpUInt8_t) oTableData;
			}
			else {
				*outData[i2].p16 = (KpUInt16_t) oTableData;
			}
			
			outData[i2].p8 += outStrideL[i2];	/* next output data location */
		}
	}
}
Esempio n. 13
0
fut_p
	fut_resize (	fut_p		fut,
					KpInt32_p	sizeArray)
{
fut_p		reSizedGtblFut = NULL, gtblFut = NULL, reSizedFut = NULL, identityFut = NULL;
KpInt32_t	i1, i2, iomask, iiomask, imask, omask, sameDims;
fut_chan_p	chan;
fut_itbl_p	itbl, itbls[FUT_NICHAN];
fut_gtbl_p	gtbls[FUT_NOCHAN];
fut_otbl_p	otbls[FUT_NOCHAN];

	#if defined KCP_DIAG_LOG
	kcpDiagLog ("fut_resize\n");
	#endif
	
	if ( ! IS_FUT(fut)) {
		return NULL;
	}

	for (i1 = 0; i1 < FUT_NICHAN; i1++) {
		itbls[i1] = FUT_NULL_ITBL;			/* init to null for freeing on error */
	}

	/* collect the gtbls from the source fut */
	/* make sure that all the gtbls use the same itbls */
	omask = 0;
	
	for (i1 = 0, sameDims = 1; i1 < FUT_NOCHAN; i1++) {
		chan = fut->chan[i1];
		if (IS_CHAN(chan)) {
			for (i2 = 0; i2 < FUT_NICHAN; i2++) {
				itbl = fut->itbl[i2];
				if (chan->itbl[i2] != itbl) {	/* must be shared */
					goto GetOut;
				}
				
				if (IS_ITBL(itbl)) {
					if (itbl->size != sizeArray [i2]) {
						sameDims = 0;			/* not the same */
					}
				}
			}

			omask |= FUT_BIT(i1);			/* resize this chan */
			gtbls[i1] = chan->gtbl;			/* collect gtbls */
		}
		else {
			gtbls[i1] = NULL;
		}
	}

	if (sameDims == 1) {
		return fut;		/* already the right size! */
	}

	imask = fut->iomask.in;
	iomask = FUT_OUT(omask) | FUT_IN(imask);
	
	/* make a new fut with these gtbls and identity itbls and otbls */
	gtblFut = fut_new (iomask, NULL, gtbls, NULL);
	if (gtblFut != NULL) {

		/* make an identity fut with itbls that have the specified sizes */
		iiomask = FUT_OUT(imask) | FUT_IN(imask);
		identityFut = constructfut (iiomask, sizeArray, NULL, NULL, NULL, NULL, KCP_FIXED_RANGE, KCP_FIXED_RANGE);
		if (identityFut != NULL) {
		
			/* compose the new size fut with the gtbl fut */
			reSizedGtblFut = fut_comp (gtblFut, identityFut, 0);
			if (reSizedGtblFut != NULL) {

				/* make a new fut with original itbls, ... */
				for (i1 = 0; i1 < FUT_NICHAN; i1++) {
					if ((imask & FUT_BIT(i1)) != 0) {
						itbls[i1] = fut_copy_itbl (fut->itbl[i1]);			/* copy (do not share!) original itbls */
						if (itbls[i1] == NULL) {
							goto GetOut;
						}
						makeMftiTblDat (itbls[i1]);							/* convert to mft to remove grid size dependancy */
						itbls[i1]->size = reSizedGtblFut->itbl[i1]->size;	/* set new grid size */
						fut_free_itbldat (itbls[i1], freeData);				/* free fixed table, it has incorrect grid indices */
					}
				}

				/* ... resized gtbls, and original otbls */
				for (i1 = 0; i1 < FUT_NOCHAN; i1++) {
					if ((omask & FUT_BIT(i1)) != 0) {
						gtbls[i1] = reSizedGtblFut->chan[i1]->gtbl;	/* collect resized gtbls */
						otbls[i1] = fut->chan[i1]->otbl;			/* and original otbls */
					}
					else {
						gtbls[i1] = NULL;
						otbls[i1] = NULL;
					}
				}

				reSizedFut = fut_new (iomask, itbls, gtbls, otbls);
			}
		}
	}

GetOut:
	fut_free (reSizedGtblFut);	/* free the intermediate futs */
	fut_free (gtblFut);
	fut_free (identityFut);
	fut_free_tbls (FUT_NICHAN, (void **)itbls);

	return (reSizedFut);
}
Esempio n. 14
0
fut_p
	fut_comp (fut_p fut1, fut_p fut0, KpInt32_t iomask)
{
KpInt32_t		ok = 1, nGridPoints, omask, evalomask, imask, pmask, order, i, j, nEntries, nOutChans;
fut_p			fut2 = NULL, evalFut = NULL;
fut_itbl_p		oitbls[FUT_NICHAN];
mf2_tbldat_p	indat[FUT_NICHAN], outdat[FUT_NOCHAN];
fut_gtbl_p		fut1_gtbls[FUT_NOCHAN];

	if (( ! IS_FUT(fut0)) || ( ! IS_FUT(fut1))) {
		return (NULL);
	}

	/* extract component masks from iomask */
	omask = FUT_OMASK(iomask);		/* which output chans? */
	pmask = FUT_PMASK(iomask);		/* which ones allowed to pass through? */
	order = FUT_ORDMASK(iomask);	/* which interpolation to use? */
	if ( order == FUT_DEFAULT ) {
		order = fut1->iomask.order;
	}

	/* adjust masks for iomask_check below */
	pmask &= fut0->iomask.out;		/* available for "pass through" */
	if ( omask == 0 ) {				/* required outputs (0 means all) */
		omask = fut1->iomask.out;
	}

	/* see if fut0 can provide required inputs to fut1 */
	imask = fut0->iomask.out;		/* available inputs for fut1 */
	iomask = FUT_OUT(omask) | FUT_IN(imask) | FUT_PASS(pmask);
	if ( ! fut_iomask_check (fut1, iomask) ) {
		return (NULL);
	}

	/* make sure the futs are in the reference state */
	if ((fut_to_mft (fut0) != 1) || (fut_to_mft (fut1) != 1)) {
		return (NULL);
	}	

	/* fut1 will be used to process the grid tables of fut0, placing the
	 * results in the grid tables of fut2.  Fut0's grid table data must first
	 * be passed through its output tables before sending it through fut1's
	 * input tables.  This is accomplished more efficiently by composing
	 * fut1's input tables with fut0's output tables and using these directly
	 * on fut0 grid data rather than the normal input tables.
	 *
	 * Create the result fut (fut2) which will be the composition of fut1
	 * and fut0.  Fut2 will inherit the input tables of fut0 and the output
	 * tables of fut1.  Its grid data will be in the same color coordinates
	 * as fut1's.
	 */
	fut2 = fut_new (FUT_IN(FUT_ALLIN), fut0->itbl, NULL, NULL);
	if ( fut2 == NULL ) {
		return (NULL);
	}

	/* for each desired channel i in fut2, create a new grid table.  The
	 * dimensions of each new grid table are derived from fut0 and fut1
	 * like so:  for every input required for channel i of fut1, form the
	 * union of the input sets of all corresponding fut0 outputs.
	 */

	/* null all io tables and table pointers */
	KpMemSet (oitbls, 0, sizeof(oitbls));

	imask = 0;			/* will be the input mask for all inputs needed to fut1 */
	evalomask = 0;		/* omask for evaluation */

	for (i = 0; (i < FUT_NOCHAN) && ok; i++) {
		KpInt32_t	size[FUT_NICHAN];
		fut_gtbl_p	gtbl;
		KpInt32_t	imask1, imask2;

		fut1_gtbls[i] = NULL;	/* assume not needed */

		if ((omask & FUT_BIT(i)) == 0) {	/* is this output channel needed? */
			continue;						/* no */
		}

		/* if a specified output is to be passed through from fut0, do that here */
		if ( ! IS_CHAN(fut1->chan[i]) && IS_CHAN(fut0->chan[i])) {

			ok = fut_defchan (fut2, FUT_OUT(FUT_BIT(i)), NULL,
							fut0->chan[i]->gtbl, fut0->chan[i]->otbl);

			continue;			/* no need to evaluate this ochan */
		}

		if (! IS_CHAN(fut1->chan[i])) {
			ok = 0;						/* something wrong */
			goto GetOut;
		}

		/* At this point we know that (fut1->chan[i] != 0).  We also
		 * have determined (from iomask_check above) that fut0->chan[j] != 0.
		 */
		imask2 = 0;						/* determine inputs from fut0 needed for this channel */
		imask1 = fut1->chan[i]->imask;	/* inputs used by this chan */

		for (j = 0; (j < FUT_NICHAN) && ok; j++) {
			if ((imask1 & FUT_BIT(j)) != 0) {		/* this input chan is needed */
				if ( ! IS_CHAN(fut0->chan[j])) {	/* available? */
					ok = 0;							/* composition fails */
					goto GetOut;
				}

				if (fut1->itbl[j] != fut1->chan[i]->itbl[j]) {	/* shared itbl? */
					goto nextOChan;								/* nope, ignore this ochan */
				}

				imask2 |= fut0->chan[j]->imask;
			}				
		}

		evalomask |= FUT_BIT(i);	/* will be evalutating this channel */
		imask |= imask1;			/* build mask of all needed inputs */
			
		/* determine required dimensions from mask */
		for (j = 0; j < FUT_NICHAN; j++) {
			size[j] = (imask2 & (KpInt32_t)FUT_BIT(j)) ? fut0->itbl[j]->size : 1;
		}

		/* create the new grid table
		 * insert it along with fut1's output table into fut2
		 */
		gtbl = fut_new_gtblEx (FUT_IN(FUT_ALLIN), NULL, NULL, size);
		ok = fut_defchan (fut2, FUT_OUT(FUT_BIT(i)), NULL, gtbl, fut1->chan[i]->otbl);
		fut_free_gtbl (gtbl);
		if (!ok) {
			goto GetOut;
		}

		fut1_gtbls[i] = fut1->chan[i]->gtbl;	/* collect gtbls for evaluation fut */

		/* verify the input data for the evaluation of the output channel in fut1 */
		for (j = 0; j < FUT_NICHAN; j++) {
			if ((imask1 & FUT_BIT(j)) != 0) {									/* this channel needed as input */
				if ((fut0->chan[j]->imask & (~fut2->chan[i]->imask)) != 0) {	/* it's inputs must be used by output */
					ok = 0;				/* composition fails */
					goto GetOut;
				}
			}
		}
nextOChan:;
	}

	/* collect the gtbls which are the input data for the chan evaluation.
	 * also pre-compose fut0's otbls with fut1's itbls.
	 */
	for (i = 0; i < FUT_NICHAN; i++) {
		oitbls[i] = NULL;

		if (ok) {
			fut_chan_p theChan = fut0->chan[i];
			
			if ((imask & FUT_BIT(i)) == 0) {
				continue;				/* this output from fut0 not required */
			}

			indat[i] = theChan->gtbl->refTbl;	/* collect gtbls: the input data for the evaluation */

			ok = (indat[i] != NULL);
			
			/* allocate memory for composed i/o tables
			 * these have the same size as the output tables of the channel supplying the input */
			if (ok) {
				fut_itbl_p	theITbl = fut1->itbl[i];
				fut_otbl_p	theOTbl = theChan->otbl;

				oitbls[i] = fut_alloc_itbl ();		/* get an itbl */

				oitbls[i]->size = theITbl->size;
				oitbls[i]->dataClass = KCP_FIXED_RANGE;

				nEntries = MAX(theITbl->refTblEntries, theOTbl->refTblEntries);

				ok = (fut_alloc_imftdat (oitbls[i], nEntries) != NULL);

				if (ok) {	/* make input table for evaluation */
					ok = fut_comp_iotblMF (theITbl, theOTbl, oitbls[i]);
				}
			}
		}
	}

	/* make an evaluation fut with the composed I/O tables, fut1's gtbls, and no otbls */
	evalFut = fut_new (iomask, oitbls, fut1_gtbls, NULL);
	if (( ! ok) ||
		(evalFut == NULL) ||		/* if evaluation fut ok */
		(fut_to_mft (fut2) != 1)) {	/* make sure the futs are in the reference state */
		ok = 0;
		goto GetOut;
	}	
	else {	/* Finally, we are ready to pass fut0's grid tables through fut1 */
		for (i = 0, nOutChans = 0; (i < FUT_NOCHAN) && ok; i++) {
			if ((evalomask & FUT_BIT(i)) != 0) {
				fut_gtbl_p	gtbl;
				
				gtbl = fut2->chan[i]->gtbl;
				nGridPoints = gtbl->tbl_size / sizeof (fut_gtbldat_t);	/* grid points for eval */

				if (evalFut->iomask.in != evalFut->chan[i]->imask) {	/* must evaluate this channel singly */
					evalomask &= ~FUT_BIT(i);							/* remove channel from multiple eval list */
					ok = evaluateFut (evalFut, FUT_BIT(i), KCM_USHORT, nGridPoints,
									(KpGenericPtr_t FAR*) indat, (KpGenericPtr_t FAR*) &(gtbl->refTbl));
				}
				else {
					outdat[nOutChans] = gtbl->refTbl;
					nOutChans++;
				}

			}
		}

		/* eval result is composed fut's gtbls */
		ok = evaluateFut (evalFut, evalomask, KCM_USHORT, nGridPoints,
						 (KpGenericPtr_t FAR*) indat, (KpGenericPtr_t FAR*) outdat);
	}

GetOut:
	/* must always free up the evaluation fut and io tables, even if an error occurred! */
	fut_free (evalFut);
	fut_free_tbls (FUT_NICHAN, (void *)oitbls);

	/* check for errors */
	if ( !ok ) {
		fut_free (fut2);
		fut2 = NULL;
	}

	return (fut2);
}
Esempio n. 15
0
/* fut_defchan defines an output channel for a fut.	Returns FALSE(0) if
 * the output channel is already defined (or fut is NULL), TRUE(1)
 * otherwise.  The size of the grid table (if non-zero) must match those
 * of the corresponding input table.  If they do not, the channel remains
 * undefined and FALSE is returned.
 *
 * If a required input table is missing, the table will be shared
 * with the corresponding one from the list of common itbls.  If there
 * is no such table in the common list, a ramp table is created and
 * inserted into the common itbl list.
 *
 * Since fut_defchan is intended to be used for constructing futs with
 * shared input tables,	if an input table is supplied that conflicts with
 * a table in the common list, an error occurs.
 */
KpInt32_t
	fut_defchan (	fut_p			fut,
					KpInt32_t		iomask,
					fut_itbl_p FAR*	itbls,
					fut_gtbl_p		gtbl,
					fut_otbl_p		otbl)
{
fut_itbl_p	itbl[FUT_NICHAN];
fut_chan_p	chan;
KpInt32_t	imask, i, tIndex;

					/* check for valid fut */
	if ( ! IS_FUT(fut)) {
		return (0);
	}
					/* get input mask */
	imask = (KpInt32_t) FUT_IMASK(iomask);

					/* get args specified by imask */
	for ( i=0, tIndex = 0; i < FUT_NICHAN; i++ ) {
		if ((itbls != NULL) && ((imask & FUT_BIT(i)) != 0)) { 	/* if itbl is in arglist, use it */
			itbl[i] = (fut_itbl_p)itbls[tIndex++];
		}
		else {	/* use itbl from shared itbl list */
			itbl[i] = fut->itbl[i];
		}
	}

	chan = fut_new_chan ((KpInt32_t)(FUT_IN (FUT_ALLIN)), (fut_itbl_p FAR*)itbl, gtbl, otbl);
	if ( ! IS_CHAN(chan)) {
		return (0);
	}

	/* If fut_new_chan created a new itbl (ramp), add it to the
	 * common list.	However, if an itbl in the chan differs from
	 * one in the common list, return an error.
	 */
	for ( i=0; i < FUT_NICHAN; i++ ) {
		if ( chan->itbl[i] == NULL ) {
			continue;
		}
		
		if ( ! IS_ITBL(fut->itbl[i])) {
			fut->itbl[i] = fut_share_itbl(chan->itbl[i]);
			fut->itblHandle[i] = chan->itblHandle[i];
		}
		else {
			if ( fut->itbl[i] != chan->itbl[i] ) {
				DIAG("fut_defchan: conflicting itbls.\n", 0);
				fut_free_chan (chan);
				return (0);
			}
		}
	}

					/* insert channel into fut */
	if ( ! fut_add_chan (fut, iomask, chan) ) {
		fut_free_chan (chan);
		return (0);
	}

	return (1);
}
Esempio n. 16
0
KpInt32_t
	TpGetDataSize (	KpHandle_t	PTHdr,
					KpHandle_t	PTData,
					PTType_t	format)
{
KpInt32_t	size, futRet, imask, omask, LUTDimensions, inputChans, outputChans;
KpInt32_t	i, tableSize, oTableEntries, gTableEntries, iTableEntries, nParaParams;
PTErr_t		errnum = KCP_INVAL_PTTYPE;
fut_hdr_p	futHdr;
fut_p		fut;
KpUInt32_t	lutConfig;

	size = 0;

	errnum = initExport (PTHdr, PTData, format, &futHdr, &fut);		/* set up to export the data */
	if (errnum == KCP_SUCCESS) {
		switch (format) {
		case PTTYPE_FUTF:
			size = fut_get_size (fut, futHdr);
		
			fut_free_tbldat (fut);	/* free the made data tables */
			break;

		case PTTYPE_MFT1:
		case PTTYPE_MFT2:
		case PTTYPE_MFT2_VER_0:
			futRet = fut_mfutInfo (fut, &LUTDimensions, &inputChans, &outputChans, format,
									&iTableEntries, &gTableEntries, &oTableEntries);

			if (futRet == 1) {
				size = inputChans * iTableEntries;	/* total input table entries */

				size += outputChans * (gTableEntries + oTableEntries);	/* plus total grid and output table entries */

				if (format == PTTYPE_MFT1) {
					size *= sizeof (mf1_tbldat_t);	/* mult by bytes in each entry */
				}
				else {
					size += 2;						/* plus input and output table counters */

					size *= sizeof (mf2_tbldat_t);	/* mult by bytes in each entry */
				}
			}
		
			fut_free_mftdat (fut);	/* free the made data tables */
			break;

		case PTTYPE_MAB1:
		case PTTYPE_MAB2:
		case PTTYPE_MBA1:
		case PTTYPE_MBA2:
		
			lutConfig = fut->lutConfig;
			/* input tables must be common and in first n contiguous input channels */
			imask = fut->iomask.in;							/* get the fut's input mask */
			for (inputChans = 0; inputChans < FUT_NICHAN; inputChans++, imask >>= 1) {
				if ( ! IS_ITBL(fut->itbl[inputChans]) || ((imask & 1) == 0)) {
					break;
				}
			}
			if (imask != 0) {
				return (0);		/* this fut can not be made into a matrix fut */
			}
			/* output tables must be in first n contiguous output channels */
			omask = fut->iomask.out;				/* get the fut's output mask */
			for (outputChans = 0; outputChans < FUT_NOCHAN; outputChans++, omask >>= 1) {
			if ( ! IS_CHAN(fut->chan[outputChans]) || ((omask & 1) == 0)) {
					break;
				}
			}
			if (omask != 0) {
				return (0);		/* this fut can not be made into a matrix fut */
			}
			tableSize = sizeof (mab_tbldat_t);

			if ((LUT_TYPE_UNKNOWN == lutConfig) || (MAB_B_CURVE_ONLY == lutConfig) ||
			(MAB_A_CLUT_B_COMBO == lutConfig) || (MBA_B_CLUT_A_COMBO == lutConfig) ||
			(MAB_A_CLUT_M_MATRIX_B_COMBO == lutConfig) || (MBA_B_MATRIX_M_CLUT_A_COMBO == lutConfig))
			{
				for (i = 0; i < inputChans; i++)
				{
					if (PARA_TYPE_SIG == fut->itbl[i]->ParaCurve.nSig)
					{
						nParaParams = getNumParaParams(fut->itbl[i]->ParaCurve.nFunction);
						size += nParaParams * sizeof (Fixed_t) + CURVETYPE_HEADER;
					} else {
						iTableEntries = fut->itbl[i]->refTblEntries;
						size += (iTableEntries * tableSize) + CURVETYPE_HEADER;	/* total input table entries */
					}
					size = (size + 3) & ~3;
				}
			}
			
			if ((LUT_TYPE_UNKNOWN == lutConfig) || (MBA_B_CLUT_A_COMBO == lutConfig) ||
			(MBA_B_MATRIX_M_CLUT_A_COMBO == lutConfig) || (MAB_A_CLUT_B_COMBO == lutConfig) ||
			(MAB_A_CLUT_M_MATRIX_B_COMBO == lutConfig))
			{
				gTableEntries = 0;
				for (i = 0; i < outputChans; i++)
				{
					gTableEntries += (fut->chan[0]->gtbl->tbl_size / sizeof (fut_gtbldat_t)); /* assume 8 bit grid tables */
				}
				if ((PTTYPE_MAB2 == format) || (PTTYPE_MBA2 == format))
				{
					gTableEntries *= 2;		/* 16 bit grid tables */
				}
				size += gTableEntries;
				size += CLUT_HEADER;
				size = (size + 3) & ~3;
			}

			if ((LUT_TYPE_UNKNOWN == lutConfig) || (MBA_B_CURVE_ONLY == lutConfig) ||
			(MAB_A_CLUT_B_COMBO == lutConfig) || (MBA_B_CLUT_A_COMBO == lutConfig) ||
			(MAB_A_CLUT_M_MATRIX_B_COMBO == lutConfig) || (MBA_B_MATRIX_M_CLUT_A_COMBO == lutConfig))
			{
				for (i = 0; i < outputChans; i++)
				{
					if (PARA_TYPE_SIG == fut->chan[i]->otbl->ParaCurve.nSig)
					{
						nParaParams = getNumParaParams(fut->chan[i]->otbl->ParaCurve.nFunction);
						size += nParaParams * sizeof (Fixed_t) + CURVETYPE_HEADER;
					} else {
						oTableEntries = fut->chan[i]->otbl->refTblEntries;
						size += (oTableEntries * tableSize + CURVETYPE_HEADER);	/* plus total output table entries */
					}
					size = (size + 3) & ~3;
				}
			}
			if ((MBA_B_MATRIX_M_CLUT_A_COMBO == lutConfig) ||
				(MBA_B_MATRIX_M_COMBO == lutConfig) || (MAB_M_MATRIX_B_COMBO == lutConfig))
			{
				for (i = 0; i < FUT_NMCHAN; i++)
				{
					if (PARA_TYPE_SIG == fut->mabInParaCurve[i].nSig)
					{
						nParaParams = getNumParaParams(fut->mabInParaCurve[i].nFunction);
						size += nParaParams * sizeof (Fixed_t) + CURVETYPE_HEADER;
					} else {
						iTableEntries = fut->mabInTblEntries[i];
						size += (iTableEntries * tableSize) + CURVETYPE_HEADER;	/* plus total matrix inputput table entries */
					}
					size = (size + 3) & ~3;
				}
			}
			if ((MAB_A_CLUT_M_MATRIX_B_COMBO == lutConfig) ||
				(MBA_B_MATRIX_M_COMBO == lutConfig) || (MAB_M_MATRIX_B_COMBO == lutConfig))
			{
				for (i = 0; i < FUT_NMCHAN; i++)
				{
					if (PARA_TYPE_SIG == fut->mabOutParaCurve[i].nSig)
					{
						nParaParams = getNumParaParams(fut->mabOutParaCurve[i].nFunction);
						size += nParaParams * sizeof (Fixed_t) + CURVETYPE_HEADER;
					} else {
						oTableEntries = fut->mabOutTblEntries[i];
						size += (oTableEntries * tableSize) + CURVETYPE_HEADER;	/* plus total matrix outputput table entries */
					}
					size = (size + 3) & ~3;
				}
			}

			fut_free_mftdat (fut);	/* free the made data tables */
			break;

		default:
			break;
		}

	 	errnum = unlockPT (PTHdr, fut);
		if (errnum != KCP_SUCCESS) {
			size = 0;
		}
	}

	return (size);
}
Esempio n. 17
0
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;
}
Esempio n. 18
0
/*---------------------------------------------------------------------------
 *  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;
}