/** Adds an attribute to the list. * This is a convenience function for adding attributes to a list. * It first searches the list to see if there is an existing attribute * with the same name. If there is it just changes the properties of the * existing attribute. If not, it creates a new attribute with the * specified properties. * IMPORTANT: This method is only capable of creating attributes * of the NDAttribute base class type, not derived class attributes. * To add attributes of a derived class to a list the NDAttributeList::add(NDAttribute*) * method must be used. * \param[in] pName The name of the attribute to be added. * \param[in] pDescription The description of the attribute. * \param[in] dataType The data type of the attribute. * \param[in] pValue A pointer to the value for this attribute. * */ NDAttribute* NDAttributeList::add(const char *pName, const char *pDescription, NDAttrDataType_t dataType, void *pValue) { //const char *functionName = "NDAttributeList::add"; NDAttribute *pAttribute; epicsMutexLock(this->lock); pAttribute = this->find(pName); if (pAttribute) { pAttribute->setDescription(pDescription); pAttribute->setValue(dataType, pValue); } else { pAttribute = new NDAttribute(pName, pDescription, dataType, pValue); ellAdd(&this->list, &pAttribute->listNode.node); } epicsMutexUnlock(this->lock); return(pAttribute); }
/** Creates a new output NDArray from an input NDArray, performing * conversion operations. * The conversion can change the data type if dataTypeOut is different from * pIn->dataType. It can also change the dimensions. outDims may have different * values of size, binning, offset and reverse for each of its dimensions from input * array dimensions (pIn->dims). * \param[in] pIn The input array, source of the conversion. * \param[out] ppOut The output array, result of the conversion. * \param[in] dataTypeOut The data type of the output array. * \param[in] dimsOut The dimensions of the output array. */ int NDArrayPool::convert(NDArray *pIn, NDArray **ppOut, NDDataType_t dataTypeOut, NDDimension_t *dimsOut) { int dimsUnchanged; size_t dimSizeOut[ND_ARRAY_MAX_DIMS]; NDDimension_t dimsOutCopy[ND_ARRAY_MAX_DIMS]; int i; NDArray *pOut; NDArrayInfo_t arrayInfo; NDAttribute *pAttribute; int colorMode, colorModeMono = NDColorModeMono; const char *functionName = "convert"; /* Initialize failure */ *ppOut = NULL; /* Copy the input dimension array because we need to modify it * but don't want to affect caller */ memcpy(dimsOutCopy, dimsOut, pIn->ndims*sizeof(NDDimension_t)); /* Compute the dimensions of the output array */ dimsUnchanged = 1; for (i=0; i<pIn->ndims; i++) { dimsOutCopy[i].size = dimsOutCopy[i].size/dimsOutCopy[i].binning; if (dimsOutCopy[i].size <= 0) { printf("%s:%s: ERROR, invalid output dimension, size=%d, binning=%d\n", driverName, functionName, (int)dimsOut[i].size, dimsOut[i].binning); return(ND_ERROR); } dimSizeOut[i] = dimsOutCopy[i].size; if ((pIn->dims[i].size != dimsOutCopy[i].size) || (dimsOutCopy[i].offset != 0) || (dimsOutCopy[i].binning != 1) || (dimsOutCopy[i].reverse != 0)) dimsUnchanged = 0; } /* We now know the datatype and dimensions of the output array. * Allocate it */ pOut = alloc(pIn->ndims, dimSizeOut, dataTypeOut, 0, NULL); *ppOut = pOut; if (!pOut) { printf("%s:%s: ERROR, cannot allocate output array\n", driverName, functionName); return(ND_ERROR); } /* Copy fields from input to output */ pOut->timeStamp = pIn->timeStamp; pOut->epicsTS = pIn->epicsTS; pOut->uniqueId = pIn->uniqueId; /* Replace the dimensions with those passed to this function */ memcpy(pOut->dims, dimsOutCopy, pIn->ndims*sizeof(NDDimension_t)); pIn->pAttributeList->copy(pOut->pAttributeList); pOut->getInfo(&arrayInfo); if (dimsUnchanged) { if (pIn->dataType == pOut->dataType) { /* The dimensions are the same and the data type is the same, * then just copy the input image to the output image */ memcpy(pOut->pData, pIn->pData, arrayInfo.totalBytes); return ND_SUCCESS; } else { /* We need to convert data types */ switch(pOut->dataType) { case NDInt8: convertTypeSwitch <epicsInt8> (pIn, pOut); break; case NDUInt8: convertTypeSwitch <epicsUInt8> (pIn, pOut); break; case NDInt16: convertTypeSwitch <epicsInt16> (pIn, pOut); break; case NDUInt16: convertTypeSwitch <epicsUInt16> (pIn, pOut); break; case NDInt32: convertTypeSwitch <epicsInt32> (pIn, pOut); break; case NDUInt32: convertTypeSwitch <epicsUInt32> (pIn, pOut); break; case NDFloat32: convertTypeSwitch <epicsFloat32> (pIn, pOut); break; case NDFloat64: convertTypeSwitch <epicsFloat64> (pIn, pOut); break; default: //status = ND_ERROR; break; } } } else { /* The input and output dimensions are not the same, so we are extracting a region * and/or binning */ /* Clear entire output array */ memset(pOut->pData, 0, arrayInfo.totalBytes); convertDimension(pIn, pOut, pIn->pData, pOut->pData, pIn->ndims-1); } /* Set fields in the output array */ for (i=0; i<pIn->ndims; i++) { pOut->dims[i].offset = pIn->dims[i].offset + dimsOutCopy[i].offset; pOut->dims[i].binning = pIn->dims[i].binning * dimsOutCopy[i].binning; if (pIn->dims[i].reverse) pOut->dims[i].reverse = !pOut->dims[i].reverse; } /* If the frame is an RGBx frame and we have collapsed that dimension then change the colorMode */ pAttribute = pOut->pAttributeList->find("ColorMode"); if (pAttribute && pAttribute->getValue(NDAttrInt32, &colorMode)) { if ((colorMode == NDColorModeRGB1) && (pOut->dims[0].size != 3)) pAttribute->setValue(&colorModeMono); else if ((colorMode == NDColorModeRGB2) && (pOut->dims[1].size != 3)) pAttribute->setValue(&colorModeMono); else if ((colorMode == NDColorModeRGB3) && (pOut->dims[2].size != 3)) pAttribute->setValue(&colorModeMono); } return ND_SUCCESS; }