Beispiel #1
0
PTErr_t
PTNewMonoPT (	ResponseRecord_p	grayTRC,
                KpUInt32_t			gridsize,
                KpBool_t			invert,
                PTRefNum_p			thePTRefNumP)
{
    PTErr_t		PTErr;
    KpInt32_t	dim[3], inSpace, outSpace;
    fut_p		theFut = NULL;

    /* Check for valid ptrs */
    PTErr = KCP_BAD_ARG;
    if (thePTRefNumP == NULL) goto GetOut;
    if (grayTRC == NULL) goto GetOut;
    if (gridsize < 2) goto GetOut;

    *thePTRefNumP = 0;

    /* all dimensions are the same */
    dim[0] = dim[1] = dim[2] = (KpInt32_t) gridsize;

    /* pass the input arguments along to the fut maker */
    if (invert == KPFALSE) {
        /* Create (1D -> 3D) FuT */
        theFut = fut_new_empty (1, dim, 3, KCP_FIXED_RANGE, KCP_LAB_PCS);
        if (theFut == NULL) {
            goto ErrOut4;
        }

        PTErr = makeForwardXformMono (grayTRC, theFut);

        inSpace = KCM_MONO;			/* setup the foward color space */
        outSpace = KCM_CIE_LAB;
    }
    else {
        /* Create (3D -> 1D) FuT */
        theFut = fut_new_empty (3, dim, 1, KCP_LAB_PCS, KCP_FIXED_RANGE);
        if (theFut == NULL) {
            goto ErrOut4;
        }

        PTErr = makeInverseXformMono (grayTRC, theFut);

        inSpace = KCM_CIE_LAB;		/* setup the inverse color space */
        outSpace = KCM_MONO;
    }

    if (PTErr != KCP_SUCCESS) {
        goto ErrOut1;
    }

    if (fut_to_mft (theFut) != 1) {			/* convert to reference tables */
        goto ErrOut3;
    }

    PTErr = fut2PT (&theFut, inSpace, outSpace, PTTYPE_CALCULATED, thePTRefNumP);	/* make into PT */
    if (PTErr != KCP_SUCCESS) {
        goto ErrOut0;
    }

GetOut:
    return (PTErr);


ErrOut4:
    PTErr = KCP_NO_MEMORY;
    goto ErrOut0;

ErrOut3:
    PTErr = KCP_INCON_PT;
    goto ErrOut0;

ErrOut1:
    PTErr = KCP_BAD_ARG;

ErrOut0:
    if (theFut != NULL) fut_free (theFut);
    if (*thePTRefNumP != 0) PTCheckOut (*thePTRefNumP);
    goto GetOut;
}
Beispiel #2
0
fut_p
	constructfut (	KpInt32_t		iomask,
					KpInt32_p		sizeArray,
					fut_calcData_p	fData,
					fut_ifunc_p		ifunArray,
					fut_gfunc_p		gfunArray,
					fut_ofunc_p		ofunArray,
					PTDataClass_t	iClass,
					PTDataClass_t	oClass)
{
fut_p		futp;
KpInt32_t	i1, imask, omask;
fut_itbl_p	itbls[FUT_NICHAN] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
fut_gtbl_p	gtbls[FUT_NOCHAN] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
fut_otbl_p	otbls[FUT_NOCHAN] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
fut_ifunc_t	ifun;
fut_gfunc_t	gfun;
fut_ofunc_t	ofun;
fData_t			fDataL;
fut_calcData_p	fDataP;

	if (sizeArray == NULL) return NULL;

	if (fData == NULL) {
		fDataP = &fDataL.std;
	}
	else {
		fDataP = fData;
	}
	
	imask = FUT_IMASK(iomask);
	omask = FUT_OMASK(iomask);

	#if defined KCP_DIAG_LOG
	{KpChar_t	string[256], str2[256];
	KpInt32_t	i1;
	sprintf (string, "constructfut\n iomask %x, sizeArray[]", iomask);
	for (i1 = 0; i1 < FUT_NICHAN; i1++) {
		if ((FUT_BIT(i1) & imask) != 0) {
			sprintf (str2, " %d", sizeArray[i1]);
			strcat (string, str2);
		}
	}
	sprintf (str2, ", fData %x, ifunArray %x, gfunArray %x, ofunArray %x, iClass %d, oClass %d\n",
					fData, ifunArray, gfunArray, ofunArray, iClass, oClass);
	strcat (string, str2);
	kcpDiagLog (string);}
	#endif
	
	/* Compute shared input tables:  */
	for (i1 = 0; i1 < FUT_NICHAN; i1++) {
		if ((imask & FUT_BIT(i1)) != 0) {
			if ((ifunArray == NULL) || (ifunArray[i1] == NULL)) {
				ifun = fut_irampEx;
				fDataP = &fDataL.std;
				if (iClass == KCP_VARIABLE_RANGE) {
					fDataL.scale = KCP_16_TO_8_ENCODING;
				}
				else {
					fDataL.scale = 1.0;
				}
			}
			else {
				ifun = ifunArray[i1];
			}

			fDataP->chan = i1;	/* define the channel # */

			itbls[i1] = fut_new_itblEx (KCP_REF_TABLES, iClass, sizeArray[i1], ifun, fDataP);
			itbls[i1]->id = fut_unique_id ();
			itbls[i1]->dataClass = iClass;
		}
	}

	/* Compute grid tables and output tables:  */
	for (i1 = 0; i1 < FUT_NOCHAN; i1++) {
		if ((omask & FUT_BIT(i1)) != 0) {
			if ((gfunArray == NULL) || (gfunArray[i1] == NULL)) {
				gfun = fut_grampEx;
			}
			else {
				gfun = gfunArray[i1];
			}

			fDataP->chan = i1;	/* define the channel # */

			gtbls[i1] = fut_new_gtblEx (KCP_REF_TABLES, iomask, gfun, fDataP, sizeArray);
			gtbls[i1]->id = fut_unique_id();

			if ((ofunArray == NULL) || (ofunArray[i1] == NULL)) {
				ofun = fut_orampEx;
				fDataP = &fDataL.std;
				if (oClass == KCP_VARIABLE_RANGE) {
					fDataL.scale = KCP_8_TO_16_ENCODING;
				}
				else {
					fDataL.scale = 1.0;
				}
			}
			else {
				ofun = ofunArray[i1];
			}

			otbls[i1] = fut_new_otblEx (KCP_REF_TABLES, oClass, ofun, fDataP);
			otbls[i1]->id = fut_unique_id();
			otbls[i1]->dataClass = oClass;
		}
	}

	/* Assemble FuT:  */
	futp = fut_new (iomask, itbls, gtbls, otbls);

	fut_free_tbls (FUT_NICHAN, (KpGenericPtr_t *)itbls);
	fut_free_tbls (FUT_NOCHAN, (KpGenericPtr_t *)gtbls);
	fut_free_tbls (FUT_NOCHAN, (KpGenericPtr_t *)otbls);

	if (fut_to_mft (futp) != 1) {		/* convert to reference tables */
		fut_free (futp);
		futp = NULL;
	}

	return (futp);
}
Beispiel #3
0
/*------------------------------------------------------------------------------
 *  PTGetRelToAbsPT -- generate a PT which
 					converts from ICC relative colorimetry to ICC absolute colorimetry
 					
 	(absolute color) = ((media white point) / (profile white point)) * (relative color)

 	so
 	(source absolute color) = ((source media white point) / (source profile white point)) * (source relative color)
 	and
 	(dest absolute color) = ((dest media white point) / (dest profile white point)) * (dest relative color)

	equating source and dest absolute colors
	 	(dest relative color) = ((source media white point) / (dest media white point))
	 						  * ((dest profile white point) / (source profile white point))
	 						  * (source relative color)

 *------------------------------------------------------------------------------
 */
PTErr_t
	 PTGetRelToAbsPT(	KpUInt32_t		RelToAbsMode,
						PTRelToAbs_p	PTRelToAbs,
						PTRefNum_p		PTRefNumPtr)
{
PTErr_t				PTErr;
KpInt32_t			status;
FloatXYZColor_t		sMWP, dMWP, sPWP, dPWP;
Fixed_t				matrix[MF_MATRIX_DIM * MF_MATRIX_DIM];
fut_p				theFutFromMatrix = NULL;

		/* just one mode now.  allows for future expansion of the function */
	if (RelToAbsMode != 0)		return KCP_NOT_IMPLEMENTED;
	if (PTRefNumPtr == NULL)	return KCP_BAD_ARG;

	*PTRefNumPtr = 0;

	sMWP.X = PTRelToAbs->srcMediaWhitePoint.X / (KpFloat32_t)KpF15d16Scale;	/* convert fixed point XYZ to floating point */
	sMWP.Y = PTRelToAbs->srcMediaWhitePoint.Y / (KpFloat32_t)KpF15d16Scale;
	sMWP.Z = PTRelToAbs->srcMediaWhitePoint.Z / (KpFloat32_t)KpF15d16Scale;
	dMWP.X = PTRelToAbs->dstMediaWhitePoint.X / (KpFloat32_t)KpF15d16Scale;
	dMWP.Y = PTRelToAbs->dstMediaWhitePoint.Y / (KpFloat32_t)KpF15d16Scale;
	dMWP.Z = PTRelToAbs->dstMediaWhitePoint.Z / (KpFloat32_t)KpF15d16Scale;
	sPWP.X = PTRelToAbs->srcProfileWhitePoint.X / (KpFloat32_t)KpF15d16Scale;
	sPWP.Y = PTRelToAbs->srcProfileWhitePoint.Y / (KpFloat32_t)KpF15d16Scale;
	sPWP.Z = PTRelToAbs->srcProfileWhitePoint.Z / (KpFloat32_t)KpF15d16Scale;
	dPWP.X = PTRelToAbs->dstProfileWhitePoint.X / (KpFloat32_t)KpF15d16Scale;
	dPWP.Y = PTRelToAbs->dstProfileWhitePoint.Y / (KpFloat32_t)KpF15d16Scale;
	dPWP.Z = PTRelToAbs->dstProfileWhitePoint.Z / (KpFloat32_t)KpF15d16Scale;
		
	matrix[0] = (Fixed_t)(((sMWP.X * dPWP.X) / (dMWP.X * sPWP.X) * KpF15d16Scale) + 0.5);	/* fill in the matrix */
	matrix[1] = 0;
	matrix[2] = 0;
	matrix[3] = 0;
	matrix[4] = (Fixed_t)(((sMWP.Y * dPWP.Y) / (dMWP.Y * sPWP.Y) * KpF15d16Scale) + 0.5);
	matrix[5] = 0;
	matrix[6] = 0;
	matrix[7] = 0;
	matrix[8] = (Fixed_t)(((sMWP.Z * dPWP.Z) / (dMWP.Z * sPWP.Z) * KpF15d16Scale) + 0.5);

	status = makeOutputMatrixXform ((Fixed_p)&matrix, PTRelToAbs->gridSize, &theFutFromMatrix);
	if (status != 1) {
		goto ErrOut1;
	}

	if (fut_to_mft (theFutFromMatrix) != 1) {		/* convert to reference tables */
		goto ErrOut3;
	}

	PTErr = fut2PT (&theFutFromMatrix, KCM_CIE_XYZ, KCM_CIE_XYZ, PTTYPE_CALCULATED, PTRefNumPtr);	/* make into PT */
	if (PTErr != KCP_SUCCESS) {
		goto ErrOut0;
	}

GetOut:
	return (PTErr);


ErrOut3:
	PTErr = KCP_INCON_PT;
	goto ErrOut0;

ErrOut1:
	PTErr = KCP_BAD_ARG;

ErrOut0:
	if (theFutFromMatrix != NULL) fut_free (theFutFromMatrix);
	if (*PTRefNumPtr != 0) PTCheckOut (*PTRefNumPtr);
	goto GetOut;
}
Beispiel #4
0
/* TpReadData reads a fut from a memory block and returns a handle to a newly allocated fut
 */
PTErr_t
	TpReadData(	KpFd_p			fd,
				PTType_t		format,
				PTRefNum_t		PTRefNum,
				KpHandle_t		PTHdr,
				KpHandle_t FAR*	PTData)
{
PTErr_t			errnum;
fut_p			fut = NULL, theFutFromMatrix = NULL, newFut = NULL, lab2xyzFut = NULL, finalFut = NULL;
fut_hdr_p		futHdr;
Fixed_t			matrix[MF_MATRIX_DIM * MF_MATRIX_DIM + MF_MATRIX_DIM];
KpInt32_t		ret, iomask;
KpChar_t		ENUM_String[20];
KpInt32_t		inCS, i, i1;
ResponseRecord_t	inRedTRC, inGreenTRC, inBlueTRC;
ResponseRecord_t	outRedTRC, outGreenTRC, outBlueTRC;
PTRefNum_t		matrixPTRefNum;
PTDataClass_t 	iClass, oClass;

	futHdr = (fut_hdr_p) lockBuffer (PTHdr);	/* get buffer pointer */
	if (futHdr == NULL) {
		errnum = KCP_MEM_LOCK_ERR;
		goto GetOut;
	}

	futHdr->profileType = getIntAttrDef (PTRefNum, KCM_ICC_PROFILE_TYPE);
	futHdr->spaceIn = getIntAttrDef (PTRefNum, KCM_SPACE_IN);
	futHdr->spaceOut = getIntAttrDef (PTRefNum, KCM_SPACE_OUT);
	futHdr->iDataClass = getDataClass (futHdr->spaceIn);
	futHdr->oDataClass = getDataClass (futHdr->spaceOut);

	switch (format) {
	case FUT_CIGAM: /* fut with bytes reversed */
	case FUT_MAGIC: /* fut with bytes in correct order */
		if ((fut = fut_alloc_fut ()) == NULL) {	/* allocate a new fut structure */
			errnum = KCP_NO_ACTIVATE_MEM;
		}
		else {
			if (fut_read_tbls (fd, fut, futHdr) != 1) {	/* read fut tables */
				errnum = KCP_PT_DATA_READ_ERR;
			}
			else {
				if (fut_io_decode (fut, futHdr) == 0) {
					errnum = KCP_PTERR_0;
				}
				else {
					errnum = KCP_SUCCESS;
				}
			}
		}
		break;

	case PTTYPE_MFT1:
	case PTTYPE_MFT2:
		fut = fut_readMFutTbls (fd, futHdr, matrix);	/* read matrix fut tables */
		if (fut == NULL) {
			errnum = KCP_NO_ACTIVATE_MEM;
		}
		else {
			inCS = getIntAttrDef (PTRefNum, KCM_SPACE_IN);

			if ((inCS == KCM_CIE_XYZ) && (isIdentityMatrix (matrix, MF_MATRIX_DIM) != 1)) {
				ret = makeOutputMatrixXform ((Fixed_p)&matrix, 8, &theFutFromMatrix);
				if (ret != 1) {
					errnum = KCP_INCON_PT;
					goto GetOut;
				}
				else {
					iomask = FUT_PASS(FUT_XYZ);		/* get the Lab to XYZ fut */
					lab2xyzFut = get_lab2xyz (KCP_GRID_DIM_SIXTEEN);

					newFut = fut_comp (theFutFromMatrix, lab2xyzFut, iomask);			

					if (newFut != NULL) {
						finalFut = fut_comp (fut, newFut, iomask);
					}			

					fut_free (theFutFromMatrix);	/* free intermediate futs */
					fut_free (lab2xyzFut);
					fut_free (fut);
					fut_free (newFut);

					fut = finalFut;

					/* set the input color space attribute to Lab */
					KpItoa (KCM_CIE_LAB, ENUM_String);
					errnum = PTSetAttribute (PTRefNum, KCM_SPACE_IN, ENUM_String);
					if (errnum != KCP_SUCCESS) {
						goto GetOut;
					}

					/* set the input composition attribute to Lab */
					errnum = PTSetAttribute (PTRefNum, KCM_IN_CHAIN_CLASS_2, "6");
					if (errnum != KCP_SUCCESS) {
						goto GetOut;
					}
				}
			}

			if ((fut == NULL) || !fut_io_encode (fut, futHdr)) {	/* make the info header */
				errnum = KCP_INCON_PT;
				goto GetOut;
			}

			errnum = KCP_SUCCESS;
		}
		break;

	case PTTYPE_MA2B:
	case PTTYPE_MB2A:
	
		matrix[0] = matrix[4] = matrix[8] = KpF15d16FromDouble(1.0);
		matrix[1] = matrix[2] = matrix[3] = 
		matrix[5] = matrix[6] = matrix[7] = 
		matrix[9] = matrix[10] = matrix[11] = KpF15d16FromDouble(0.0);
		
		fut = fut_readMabFutTbls (fd, futHdr, matrix);	/* read matrix fut tables */
		if (fut == NULL) {
			errnum = KCP_NO_ACTIVATE_MEM;
		}
		else {
			if (fut->lutConfig & HAS_MATRIX_DATA) {
				i = MF_MATRIX_DIM * MF_MATRIX_DIM + MF_MATRIX_DIM;
				for (i1 = 0; i1 < i; i1++)
				{
					fut->matrix[i1] = matrix[i1];
				}
				switch (fut->lutConfig) {
				case MAB_M_MATRIX_B_COMBO:
				case MBA_B_MATRIX_M_COMBO:
					inRedTRC.CurveCount = fut->mabInTblEntries[0];
					inGreenTRC.CurveCount = fut->mabInTblEntries[1];
					inBlueTRC.CurveCount = fut->mabInTblEntries[2];
					inRedTRC.CurveData = fut->mabInRefTbl[0];
					inGreenTRC.CurveData = fut->mabInRefTbl[1];
					inBlueTRC.CurveData = fut->mabInRefTbl[2];
					outRedTRC.CurveCount = fut->mabOutTblEntries[0];
					outGreenTRC.CurveCount = fut->mabOutTblEntries[1];
					outBlueTRC.CurveCount = fut->mabOutTblEntries[2];
					outRedTRC.CurveData = fut->mabOutRefTbl[0];
					outGreenTRC.CurveData = fut->mabOutRefTbl[1];
					outBlueTRC.CurveData = fut->mabOutRefTbl[2];
					iClass = getDataClass(futHdr->spaceIn);
					oClass = getDataClass(futHdr->spaceOut);
					ret = makeFutFromMatrix ((Fixed_p)&matrix, &inRedTRC, &inGreenTRC, &inBlueTRC, 
												&outRedTRC, &outGreenTRC, &outBlueTRC, MATRIX_GRID_SIZE, iClass, oClass, 
												(fut_p *)&theFutFromMatrix);
					break;

				case MBA_B_MATRIX_M_CLUT_A_COMBO:
					inRedTRC.CurveCount = fut->mabInTblEntries[0];
					inGreenTRC.CurveCount = fut->mabInTblEntries[1];
					inBlueTRC.CurveCount = fut->mabInTblEntries[2];
					inRedTRC.CurveData = fut->mabInRefTbl[0];
					inGreenTRC.CurveData = fut->mabInRefTbl[1];
					inBlueTRC.CurveData = fut->mabInRefTbl[2];
					iClass = getDataClass(futHdr->spaceIn);
					oClass = KCP_UNKNOWN;
					ret = makeFutFromMatrix ((Fixed_p)&matrix, &inRedTRC, &inGreenTRC, &inBlueTRC, 
												NULL, NULL, NULL, MATRIX_GRID_SIZE, iClass, oClass, (fut_p *)&theFutFromMatrix);
					break;

				case MAB_A_CLUT_M_MATRIX_B_COMBO:
					outRedTRC.CurveCount = fut->mabOutTblEntries[0];
					outGreenTRC.CurveCount = fut->mabOutTblEntries[1];
					outBlueTRC.CurveCount = fut->mabOutTblEntries[2];
					outRedTRC.CurveData = fut->mabOutRefTbl[0];
					outGreenTRC.CurveData = fut->mabOutRefTbl[1];
					outBlueTRC.CurveData = fut->mabOutRefTbl[2];
					iClass = KCP_UNKNOWN;
					oClass = getDataClass(futHdr->spaceOut);
					ret = makeFutFromMatrix ((Fixed_p)&matrix, NULL, NULL, NULL, &outRedTRC, &outGreenTRC,
												&outBlueTRC, MATRIX_GRID_SIZE, iClass, oClass, (fut_p *)&theFutFromMatrix);
					break;

				default:
					break;
				}
				if (NULL != theFutFromMatrix)
				{
					/* Create a PT from the fut */
					errnum = fut2PT (&theFutFromMatrix, KCM_UNKNOWN, KCM_UNKNOWN, PTTYPE_CALCULATED, &matrixPTRefNum);
					if (errnum != KCP_SUCCESS) {
						goto GetOut;
					}
					errnum = setMatrixPTRefNum (PTRefNum, matrixPTRefNum, fut->lutConfig);
					if (errnum != KCP_SUCCESS) {
						goto GetOut;
					}
				}
				if (ret != 1) {
					errnum = KCP_INCON_PT;
					goto GetOut;
				}
			}

			if ((fut == NULL) || !fut_io_encode (fut, futHdr)) {	/* make the info header */
				errnum = KCP_INCON_PT;
				goto GetOut;
			}

			errnum = KCP_SUCCESS;
		}
		break;

	default:
		break;
	}


GetOut:
	if ((errnum != KCP_SUCCESS) || (fut == NULL)) {
		fut_free (fut);
	}
	else {		/* return handle to fut to caller */

	/* make sure the futs are in the reference state */
		if (fut_to_mft (fut) == 1) {
			*PTData = (KpHandle_t)fut_unlock_fut (fut);
		}
	}

	if ( ! unlockBuffer (PTHdr)) {
		errnum = KCP_MEM_UNLOCK_ERR;
	}

	return errnum;
}
Beispiel #5
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);
}
Beispiel #6
0
/* gridDimValid determines whether the grid table dimensions are valid
 * for the format specified.  If the dimensions are not valid then the
 * function attempts to create a
 * PT with the correct size grid tables.  If it is successful the
 * PTRefNum of the resized PT is returned in the location pointed to by
 * resizePTRefNumP.  If resizing is not required the value returned in 
 * the location pointed to by resizePTRefNumP is 0.
 *
 * NOTE:  	If this function creates a resized PT, that PT is checked in.  
 *			it is the responsibility of the calling function to check out
 *			that PT.
 */
static PTErr_t
	gridDimValid (	PTType_t	format,
					PTRefNum_t	PTRefNum,
					PTRefNum_p	resizePTRefNumP)
{
KpHandle_t	PTData;
KpInt32_t	inputChans, outputChans, LUTDimensions, dummy = 0;
fut_p	 	fut;
PTErr_t		retVal, error = KCP_SUCCESS;

	/*	Assume no resizing */
	if (NULL != resizePTRefNumP) {
		*resizePTRefNumP = 0;
	}

	/*	Convert the PTRefNum to a fut */
	PTData = getPTData (PTRefNum);
	fut = fut_lock_fut (PTData);
	if (fut == FUT_NULL) {
		return KCP_PTERR_2;
	}

	if ( ! IS_FUT (fut) ) {	/* check for valid fut */
		retVal = KCP_NOT_FUT;
		goto GetOut;
	}

	switch (format ) {

#if !defined KCP_ICC_ONLY
	case PTTYPE_FUTF:
		/* 	may want to check if any of the grid dimensions exceed the max 
			grid dimension, but for now accept any size						*/
		break;
#endif
	case PTTYPE_MAB1:
	case PTTYPE_MAB2:
	case PTTYPE_MBA1:
	case PTTYPE_MBA2:
		/* 	may want to check if any of the grid dimensions exceed the max 
			grid dimension, but for now accept any size						*/
		break;

	case PTTYPE_MFT1:
	case PTTYPE_MFT2:
	case PTTYPE_MFT2_VER_0:
		/*	The grid dimensions must all be the same.  If they are not then
			attempt to build a grid table where all the dimensions are the
			same.															*/
		retVal = (PTErr_t) fut_mfutInfo (fut, &LUTDimensions, &inputChans, &outputChans, format,
										&dummy, &dummy, &dummy);
		if (1 != retVal) {
			if (-2 != retVal) {
				retVal = KCP_INVAL_GRID_DIM;
				goto GetOut;
			}
			else {
				KpInt32_t	i1, newGridDims[FUT_NICHAN];
				fut_p		futresized;

				for (i1 = 0; i1 < FUT_NICHAN; i1++) {		/* define new grid sizes */
					newGridDims[i1] = LUTDimensions;
				}

				futresized = fut_resize (fut, newGridDims);	/* resize the fut */
				if (futresized == NULL) {
					retVal = KCP_NO_MEMORY;
					goto GetOut;
				}

				if (futresized == fut) {					/* should not happen, probably fut_mfutInfo() error */
					retVal = KCP_SYSERR_3;
					goto GetOut;
				}

				if (fut_to_mft (futresized) != 1) {			/* convert to reference tables */
					retVal = KCP_INCON_PT;
					goto GetOut;
				}

				retVal = fut2PT (&futresized, -1, -1, PTTYPE_CALCULATED, resizePTRefNumP);	/* make into PT */
				if (retVal == KCP_SUCCESS) {
					retVal = copyAllAttr (PTRefNum, *resizePTRefNumP);	/* Copy all attributes to new PT */
					if (retVal != KCP_SUCCESS) {
						PTCheckOut (*resizePTRefNumP);
						goto GetOut;
					}
				}
 			}
		}
		break;

	default:
		retVal = KCP_INVAL_PTTYPE;
	}

	retVal = KCP_SUCCESS;

GetOut:
	fut_unlock_fut (fut);
	return retVal;
}