/* 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); }
/* 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; }
/* PTGetSizeF calculates the size of a PT in any format. */ PTErr_t PTGetSizeF (PTRefNum_t PTRefNum, PTType_t format, KpInt32_p mBlkSize) { PTErr_t errnum, errnum1; KpInt32_t extSize, intSize; KpHandle_t PTHdr, PTData; PTRefNum_t matrixPTRefNum; KpUInt32_t lutConfig; #if !defined KCP_ICC_ONLY KpHandle_t PTAttr; #endif #if !defined KCMS_NO_CRC KpChar_t strCRCmade[KCM_MAX_ATTRIB_VALUE_LENGTH+1]; KpInt32_t crc32; #endif errnum = getPTStatus (PTRefNum); if ((errnum == KCP_PT_ACTIVE) || (errnum == KCP_PT_INACTIVE) || (errnum == KCP_SERIAL_PT)) { if (mBlkSize == NULL) return (KCP_BAD_PTR); switch (format) { #if !defined KCP_ICC_ONLY case PTTYPE_FUTF: extSize = KCP_PT_HEADER_SIZE; /* size of external header */ break; #endif case PTTYPE_MFT1: case PTTYPE_MFT2: case PTTYPE_MFT2_VER_0: extSize = (2 * sizeof (KpInt32_t)) + (4 * sizeof (KpUInt8_t)) + (MF_MATRIX_DIM * MF_MATRIX_DIM * sizeof (KpInt32_t)); break; case PTTYPE_MAB1: case PTTYPE_MAB2: case PTTYPE_MBA1: case PTTYPE_MBA2: extSize = (7 * sizeof (KpInt32_t)) + (2 * sizeof (KpUInt8_t)) + sizeof (KpUInt16_t); errnum1 = getMatrixPTRefNum (PTRefNum, &matrixPTRefNum, &lutConfig); if (KCP_SUCCESS == errnum1) { extSize += ((MF_MATRIX_DIM * MF_MATRIX_DIM + MF_MATRIX_DIM) * sizeof (KpInt32_t)); } break; default: return (KCP_INVAL_PTTYPE); } if ((errnum == KCP_PT_ACTIVE) || (errnum == KCP_SERIAL_PT)) { /* when active, add size of external PT data block */ PTHdr = getPTHdr (PTRefNum); PTData = getPTData (PTRefNum); intSize = TpGetDataSize (PTHdr, PTData, format); if (intSize == 0) { PTRefNum_t resizePTRefNum; /* TpGetDataSize will return 0 if the grid table dimensions are not valid for the format specified. PTGetPTF will attempt to resize the grid table of the PT. Check if that resizing is possible */ errnum = gridDimValid (format, PTRefNum, &resizePTRefNum); if (errnum != KCP_SUCCESS) { return errnum; } /* Determine the size of the resized PT */ PTHdr = getPTHdr (resizePTRefNum); PTData = getPTData (resizePTRefNum); intSize = TpGetDataSize (PTHdr, PTData, format); PTCheckOut (resizePTRefNum); if (intSize == 0) { return KCP_INCON_PT; } } extSize += intSize; /* add size of data */ #if !defined KCMS_NO_CRC switch (format) { case PTTYPE_FUTF: errnum = TpCalCrc (PTHdr, PTData, &crc32); if (errnum == KCP_SUCCESS) { KpItoa(crc32, strCRCmade); PTSetAttribute(PTRefNum, KCM_CRC, strCRCmade); } break; default: break; } #endif } /* add size of attributes. Must be done after CRC calculation */ #if !defined KCP_ICC_ONLY switch (format) { case PTTYPE_FUTF: PTAttr = getPTAttr (PTRefNum); extSize += getAttrSize(PTAttr); /* plus size of attributes */ break; default: break; } #endif *mBlkSize = extSize; /* return external size of PT */ errnum = KCP_SUCCESS; } return (errnum); }
/* PTGetPTF writes a PT to external memory in a variety of formats. */ PTErr_t PTGetPTF ( PTRefNum_t PTRefNum, PTType_t format, KpInt32_t mBlkSize, PTAddr_t PTAddr) { PTErr_t errnum, PTstatus; KpHandle_t PTHdr, PTAttr, PTData; KpFd_t fd; KpInt32_t attrSize, resultSize, nBytes; PTRefNum_t resizePTRefNum = 0, thePTRefNum; KpChar_p memData; errnum = getPTStatus (PTRefNum); if ((errnum == KCP_PT_ACTIVE) || (errnum == KCP_PT_INACTIVE) || (errnum == KCP_SERIAL_PT)) { #if defined KCP_DIAG_LOG {KpChar_t string[256]; sprintf (string, "\nPTGetPTF\n PTRefNum %x, format %x, mBlkSize %d, PTAddr %x\n", PTRefNum, format, mBlkSize, PTAddr); kcpDiagLog (string);} #endif PTstatus = errnum; /* verify the dimensions of the grid table are valid for the specified format. */ errnum = gridDimValid (format, PTRefNum, &resizePTRefNum); if (errnum != KCP_SUCCESS) { goto ErrOut1; } if (resizePTRefNum != 0) { thePTRefNum = resizePTRefNum; /* resized PT made */ } else { thePTRefNum = PTRefNum; /* use original PT */ } /* determine the size the resized PT */ errnum = PTGetSizeF (thePTRefNum, format, &resultSize); if (errnum != KCP_SUCCESS) { goto ErrOut1; } if (resultSize > mBlkSize) { /* PT may not be larger than the buffer size */ errnum = KCP_PT_BLOCK_TOO_SMALL; goto ErrOut1; } PTAttr = getPTAttr (thePTRefNum); PTHdr = getPTHdr (thePTRefNum); PTData = getPTData (thePTRefNum); /* initialize memory file manager to write the PT */ if (KpOpen (NULL, "m", &fd, NULL, (KpGenericPtr_t)PTAddr, mBlkSize) != KCMS_IO_SUCCESS) { errnum = KCP_SYSERR_1; goto ErrOut1; } attrSize = getAttrSize (PTAttr); /* get size of attributes */ errnum = TpWriteHdr (&fd, format, PTHdr, attrSize); /* write the header info */ if (errnum != KCP_SUCCESS) { Kp_close (&fd); goto ErrOut1; } #if !defined KCP_ICC_ONLY switch (format) { case PTTYPE_FUTF: errnum = writeAttributes (&fd, PTAttr); /* write the attributes */ if (errnum != KCP_SUCCESS) { break; } default: break; } #endif /* if PT active, write data to external format */ if (((PTstatus == KCP_PT_ACTIVE) || (PTstatus == KCP_SERIAL_PT)) && (errnum == KCP_SUCCESS)) { errnum = TpWriteData (&fd, format, PTHdr, PTData); } (void) Kp_close (&fd); /* if the result PT size is smaller than the memory block size fill the end of the memory block with zeros */ nBytes = mBlkSize - resultSize; if (nBytes > 0) { memData = (KpChar_p)PTAddr + resultSize; while (nBytes--) { *memData++ = 0; } } } ErrOut1: if (resizePTRefNum != 0) { PTCheckOut (resizePTRefNum); } return (errnum); }
PTErr_t PTEvaluate ( PTRefNum_t PTRefNum, PTEvalDTPB_p evalDef, PTEvalTypes_t evalID, KpInt32_t devNum, KpInt32_t aSync, opRefNum_p opRefNum, callBack_p callBack) { PTErr_t PTErr; PTEvalDTPB_t lEvalDef; PTCompDef_t thisInput [FUT_NICHAN], thisOutput [FUT_NOCHAN]; PTRefNum_t PTList [MAX_PT_CHAIN_SIZE]; PTTable_p evalList [MAX_PT_CHAIN_SIZE], PTTableP; PTTable_p* listStart; KpInt32_t theSerialCount, i1, i2, i3, i4, nOutputs, nFuts, PTcount; KpUInt32_t tempMemNeeded, oMask, ioMaskList [MAX_PT_CHAIN_SIZE]; PTImgAddr_t addr; #if defined (KCP_ACCEL) PTEvalTypes_t evaluator; KpInt32_t numEvals; #endif if (devNum) {} if (aSync) {} if (opRefNum) {} #if defined (KCP_MACPPC_MP) KCPInitializeMP (); #endif PTErr = getPTStatus (PTRefNum); /* must be an active or serial PT */ if ((PTErr != KCP_PT_ACTIVE) && (PTErr != KCP_SERIAL_PT)) { goto ErrOut0; } #if defined (KCP_ACCEL) PTErr = GetEval (evalID, &evaluator); /* get an evaluator */ if (PTErr != KCP_SUCCESS) { goto ErrOut0; } #endif /* valid PTEvalDTPB_p? */ if (evalDef == NULL) goto ErrOut1; if (evalDef->input == NULL) goto ErrOut1; if (evalDef->output == NULL) goto ErrOut1; if (evalDef->nInputs > FUT_NICHAN) goto ErrOut3; if (evalDef->nOutputs > FUT_NOCHAN) goto ErrOut3; /* set up the local evaluation structures */ /* set input and output to NULL */ /* this preserves the channel position while allowing */ /* the number of channels to indicate the number of valid addresses */ /* this is needed to keep both the CTE and SW evaluations happy */ for (i1 = 0; i1 < FUT_NICHAN; i1++) { thisInput[i1].pelStride = 0; thisInput[i1].lineStride = 0; thisInput[i1].addr = NULL; } lEvalDef.nPels = evalDef->nPels; lEvalDef.nLines = evalDef->nLines; lEvalDef.nInputs = FUT_NICHAN; lEvalDef.dataTypeI = evalDef->dataTypeI; lEvalDef.input = thisInput; for (i1 = 0; i1 < evalDef->nInputs; i1++) { lEvalDef.input[i1].pelStride = evalDef->input[i1].pelStride; lEvalDef.input[i1].lineStride = evalDef->input[i1].lineStride; lEvalDef.input[i1].addr = evalDef->input[i1].addr; } /* output addresses are loaded in the evaluation loop, no need to do anything here */ /* clear the PT and evaluation lists, just for clarity */ for (i1 = 0; i1 < MAX_PT_CHAIN_SIZE; i1++) { PTList[i1] = NULL; evalList[i1] = NULL; } /* get the list of PTs which we must actually evaluate */ PTErr = resolvePTData (PTRefNum, &theSerialCount, PTList); /* set up list of futs through which the image is evaluated */ for (i1 = 0; i1 < theSerialCount; i1++) { PTTableP = lockPTTable (PTList[i1]); /* lock tables while evaluating */ evalList[i1] = PTTableP; } /* initialize the evaluation list */ PTErr = setupEvalList (theSerialCount, evalList, ioMaskList, evalDef, &tempMemNeeded); if (PTErr != KCP_SUCCESS) { goto ErrOut2; } /* if temporary memory is not needed, */ /* then evaluate a full image at a time until */ /* the image has been processed through all futs */ /* if temporary memory is needed, */ /* then this level processes the image just once */ /* and a lower level processes the image through all futs */ if (tempMemNeeded == 0) { PTcount = theSerialCount; } else { PTcount = 1; } initProgressPasses (PTcount, callBack); /* process the image through each fut in the list */ for (i1 = 0; i1 < PTcount; i1++) { /* set up the output data addresses */ /* use io mask to order output channels properly */ if (tempMemNeeded == 1) { nFuts = theSerialCount; /* this many futs to evaluate */ listStart = &evalList[0]; oMask = FUT_OMASK(ioMaskList[nFuts-1]); /* use mask of last fut */ } else { nFuts = 1; /* evaluate one fut */ listStart = &evalList[i1]; oMask = FUT_OMASK(ioMaskList[i1]); /* use mask of this fut */ } /* initialize the output data structures */ lEvalDef.nOutputs = FUT_NOCHAN; lEvalDef.dataTypeO = evalDef->dataTypeO; lEvalDef.output = thisOutput; for (i2 = 0; i2 < FUT_NOCHAN; i2++) { thisOutput[i2].pelStride = 0; thisOutput[i2].lineStride = 0; thisOutput[i2].addr = NULL; } /* set the output channel addresses */ if (i1 == (PTcount -1)) { /* last, just use supplied stuff */ for (i2 = 0, nOutputs = 0; i2 < evalDef->nOutputs; i2++) { lEvalDef.output[i2].pelStride = evalDef->output[i2].pelStride; lEvalDef.output[i2].lineStride = evalDef->output[i2].lineStride; lEvalDef.output[i2].addr = evalDef->output[i2].addr; nOutputs++; /* count actual outputs */ } getDataBytes (evalDef->dataTypeO, &i3); /* get output data size */ if (i3 == 0) { nOutputs = 3; } } else { for (i2 = oMask, i3 = 0, i4 = 0, nOutputs = 0; i2 != 0; i2 >>= 1, i3++) { if ((i2 & 1) == 1) { /* this output channel is needed */ while ((addr = evalDef->output[i4].addr) == NULL) { i4++; /* get next available output channel */ } if (i4 > evalDef->nOutputs) { PTErr = KCP_PTERR_4; /* programming error */ goto ErrOut2; } lEvalDef.output[i3].pelStride = evalDef->output[i4].pelStride; lEvalDef.output[i3].lineStride = evalDef->output[i4].lineStride; lEvalDef.output[i3].addr = addr; i4++; /* next output address */ nOutputs++; /* count actual outputs */ } } } #if defined (KCP_ACCEL) /* if there are less than FASTER_IN_SW evaluations, it's faster to do it in software. */ numEvals = lEvalDef.nPels * lEvalDef.nLines * nOutputs; if ((numEvals < FASTER_IN_SW) || (tempMemNeeded == 1)) { evaluator = KCP_EVAL_SW; } switch (evaluator) { case KCP_EVAL_SW: /* evaluate in software */ software_evaluation: #endif PTErr = PTEvalSeq (nFuts, listStart, ioMaskList, &lEvalDef, callBack); if (PTErr != KCP_SUCCESS) { goto ErrOut2; } #if defined (KCP_ACCEL) break; case KCP_EVAL_CTE: /* evaluate using the NFE */ { PTRefNum_t thePTRefNum; KpHandle_t PTData; thePTRefNum = listStart[0]->refNum; /* get the PT reference number */ PTData = getPTData (thePTRefNum); /* get the transform data */ PTErr = PT_eval_cteDT (PTData, &lEvalDef, 0, 0, callBack); if ((PTErr == KCP_CTE_GRID_TOO_BIG) || (PTErr == KCP_CTE_NOT_ATTEMPTED)) { goto software_evaluation; } break; } default: PTErr = KCP_INVAL_EVAL; break; } #else if (evalID) {} /* unreferenced formal parameter */ #endif /* output for this PT is input for next PT */ lEvalDef.nInputs = lEvalDef.nOutputs; lEvalDef.dataTypeI = lEvalDef.dataTypeO; for (i2 = 0; i2 < lEvalDef.nInputs; i2++) { lEvalDef.input[i2].pelStride = lEvalDef.output[i2].pelStride; lEvalDef.input[i2].lineStride = lEvalDef.output[i2].lineStride; lEvalDef.input[i2].addr = lEvalDef.output[i2].addr; } } ErrOut2: /* unlock the PTs used for evaluation */ for (i1 = 0; i1 < theSerialCount; i1++) { unlockPTTable (PTList[i1]); } ErrOut0: return (PTErr); ErrOut1: PTErr = KCP_BAD_PTR; goto ErrOut0; ErrOut3: PTErr = KCP_INVAL_EVAL; goto ErrOut0; }