void NTNDArrayConverter::fromAttributes (NDArray *src) { PVStructureArrayPtr dest(m_array->getAttribute()); NDAttributeList *srcList = src->pAttributeList; NDAttribute *attr = NULL; StructureConstPtr structure(dest->getStructureArray()->getStructure()); PVStructureArray::svector destVec(dest->reuse()); destVec.resize(srcList->count()); size_t i = 0; while((attr = srcList->next(attr))) { if(!destVec[i].get() || !destVec[i].unique()) destVec[i] = PVDC->createPVStructure(structure); PVStructurePtr pvAttr(destVec[i]); pvAttr->getSubField<PVString>("name")->put(attr->getName()); pvAttr->getSubField<PVString>("descriptor")->put(attr->getDescription()); pvAttr->getSubField<PVString>("source")->put(attr->getSource()); NDAttrSource_t sourceType; attr->getSourceInfo(&sourceType); pvAttr->getSubField<PVInt>("sourceType")->put(sourceType); switch(attr->getDataType()) { case NDAttrInt8: fromAttribute <PVByte, int8_t> (pvAttr, attr); break; case NDAttrUInt8: fromAttribute <PVUByte, uint8_t> (pvAttr, attr); break; case NDAttrInt16: fromAttribute <PVShort, int16_t> (pvAttr, attr); break; case NDAttrUInt16: fromAttribute <PVUShort, uint16_t>(pvAttr, attr); break; case NDAttrInt32: fromAttribute <PVInt, int32_t> (pvAttr, attr); break; case NDAttrUInt32: fromAttribute <PVUInt, uint32_t>(pvAttr, attr); break; case NDAttrFloat32: fromAttribute <PVFloat, float> (pvAttr, attr); break; case NDAttrFloat64: fromAttribute <PVDouble, double> (pvAttr, attr); break; case NDAttrString: fromStringAttribute(pvAttr, attr); break; case NDAttrUndefined: fromUndefinedAttribute(pvAttr); break; default: throw std::runtime_error("invalid attribute data type"); } ++i; } dest->replace(freeze(destVec)); }
/** Opens a TIFF file. * \param[in] fileName The name of the file to open. * \param[in] openMode Mask defining how the file should be opened; bits are * NDFileModeRead, NDFileModeWrite, NDFileModeAppend, NDFileModeMultiple * \param[in] pArray A pointer to an NDArray; this is used to determine the array and attribute properties. */ asynStatus NDFileTIFF::openFile(const char *fileName, NDFileOpenMode_t openMode, NDArray *pArray) { /* When we create TIFF variables and dimensions, we get back an * ID for each one. */ static const char *functionName = "openFile"; size_t sizeX, sizeY, rowsPerStrip; int bitsPerSample=8, sampleFormat=SAMPLEFORMAT_INT, samplesPerPixel, photoMetric, planarConfig; int colorMode=NDColorModeMono; NDAttribute *pAttribute = NULL; char tagString[MAX_ATTRIBUTE_STRING_SIZE] = {0}; char attrString[MAX_ATTRIBUTE_STRING_SIZE] = {0}; /* We don't support reading yet */ if (openMode & NDFileModeRead) return(asynError); /* We don't support opening an existing file for appending yet */ if (openMode & NDFileModeAppend) return(asynError); /* Create the file. */ if ((this->output = TIFFOpen(fileName, "w")) == NULL ) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s error opening file %s\n", driverName, functionName, fileName); return(asynError); } /* We do some special treatment based on colorMode */ pAttribute = pArray->pAttributeList->find("ColorMode"); if (pAttribute) pAttribute->getValue(NDAttrInt32, &colorMode); switch (pArray->dataType) { case NDInt8: sampleFormat = SAMPLEFORMAT_INT; bitsPerSample = 8; break; case NDUInt8: sampleFormat = SAMPLEFORMAT_UINT; bitsPerSample = 8; break; case NDInt16: sampleFormat = SAMPLEFORMAT_INT; bitsPerSample = 16; break; case NDUInt16: sampleFormat = SAMPLEFORMAT_UINT; bitsPerSample = 16; break; case NDInt32: sampleFormat = SAMPLEFORMAT_INT; bitsPerSample = 32; break; case NDUInt32: sampleFormat = SAMPLEFORMAT_UINT; bitsPerSample = 32; break; case NDFloat32: sampleFormat = SAMPLEFORMAT_IEEEFP; bitsPerSample = 32; break; case NDFloat64: sampleFormat = SAMPLEFORMAT_IEEEFP; bitsPerSample = 64; break; } if (pArray->ndims == 2) { sizeX = pArray->dims[0].size; sizeY = pArray->dims[1].size; rowsPerStrip = sizeY; samplesPerPixel = 1; photoMetric = PHOTOMETRIC_MINISBLACK; planarConfig = PLANARCONFIG_CONTIG; this->colorMode = NDColorModeMono; } else if ((pArray->ndims == 3) && (pArray->dims[0].size == 3) && (colorMode == NDColorModeRGB1)) { sizeX = pArray->dims[1].size; sizeY = pArray->dims[2].size; rowsPerStrip = sizeY; samplesPerPixel = 3; photoMetric = PHOTOMETRIC_RGB; planarConfig = PLANARCONFIG_CONTIG; this->colorMode = NDColorModeRGB1; } else if ((pArray->ndims == 3) && (pArray->dims[1].size == 3) && (colorMode == NDColorModeRGB2)) { sizeX = pArray->dims[0].size; sizeY = pArray->dims[2].size; rowsPerStrip = 1; samplesPerPixel = 3; photoMetric = PHOTOMETRIC_RGB; planarConfig = PLANARCONFIG_SEPARATE; this->colorMode = NDColorModeRGB2; } else if ((pArray->ndims == 3) && (pArray->dims[2].size == 3) && (colorMode == NDColorModeRGB3)) { sizeX = pArray->dims[0].size; sizeY = pArray->dims[1].size; rowsPerStrip = sizeY; samplesPerPixel = 3; photoMetric = PHOTOMETRIC_RGB; planarConfig = PLANARCONFIG_SEPARATE; this->colorMode = NDColorModeRGB3; } else { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: unsupported array structure\n", driverName, functionName); return(asynError); } /* this is in the unallocated 'reusable' range */ static const int TIFFTAG_NDTIMESTAMP = 65000; static const int TIFFTAG_UNIQUEID = 65001; static const int TIFFTAG_EPICSTSSEC = 65002; static const int TIFFTAG_EPICSTSNSEC = 65003; static const TIFFFieldInfo NDTimeStampFI = { TIFFTAG_NDTIMESTAMP,1,1,TIFF_DOUBLE,FIELD_CUSTOM,1,0,(char *)"NDTimeStamp" }; static const TIFFFieldInfo NDUniqueIdFI = { TIFFTAG_UNIQUEID,1,1,TIFF_LONG,FIELD_CUSTOM,1,0,(char *)"NDUniqueId" }; static const TIFFFieldInfo EPICSTSSecFI = { TIFFTAG_EPICSTSSEC,1,1,TIFF_LONG,FIELD_CUSTOM,1,0,(char *)"EPICSTSSec" }; static const TIFFFieldInfo EPICSTSNsecFI = { TIFFTAG_EPICSTSNSEC,1,1,TIFF_LONG,FIELD_CUSTOM,1,0,(char *)"EPICSTSNsec" }; TIFFMergeFieldInfo(output, &NDTimeStampFI, 1); TIFFMergeFieldInfo(output, &NDUniqueIdFI, 1); TIFFMergeFieldInfo(output, &EPICSTSSecFI, 1); TIFFMergeFieldInfo(output, &EPICSTSNsecFI, 1); TIFFSetField(this->output, TIFFTAG_NDTIMESTAMP, pArray->timeStamp); TIFFSetField(this->output, TIFFTAG_UNIQUEID, pArray->uniqueId); TIFFSetField(this->output, TIFFTAG_EPICSTSSEC, pArray->epicsTS.secPastEpoch); TIFFSetField(this->output, TIFFTAG_EPICSTSNSEC, pArray->epicsTS.nsec); TIFFSetField(this->output, TIFFTAG_BITSPERSAMPLE, bitsPerSample); TIFFSetField(this->output, TIFFTAG_SAMPLEFORMAT, sampleFormat); TIFFSetField(this->output, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel); TIFFSetField(this->output, TIFFTAG_PHOTOMETRIC, photoMetric); TIFFSetField(this->output, TIFFTAG_PLANARCONFIG, planarConfig); TIFFSetField(this->output, TIFFTAG_IMAGEWIDTH, (epicsUInt32)sizeX); TIFFSetField(this->output, TIFFTAG_IMAGELENGTH, (epicsUInt32)sizeY); TIFFSetField(this->output, TIFFTAG_ROWSPERSTRIP, (epicsUInt32)rowsPerStrip); this->pFileAttributes->clear(); this->getAttributes(this->pFileAttributes); pArray->pAttributeList->copy(this->pFileAttributes); pAttribute = this->pFileAttributes->find("Model"); if (pAttribute) { pAttribute->getValue(NDAttrString, tagString); TIFFSetField(this->output, TIFFTAG_MODEL, tagString); } else { TIFFSetField(this->output, TIFFTAG_MODEL, "Unknown"); } pAttribute = this->pFileAttributes->find("Manufacturer"); if (pAttribute) { pAttribute->getValue(NDAttrString, tagString); TIFFSetField(this->output, TIFFTAG_MAKE, tagString); } else { TIFFSetField(this->output, TIFFTAG_MAKE, "Unknown"); } TIFFSetField(this->output, TIFFTAG_SOFTWARE, "EPICS areaDetector"); int count = 0; int tagId = TIFFTAG_START_; numAttributes_ = this->pFileAttributes->count(); asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s this->pFileAttributes->count(): %d\n", driverName, functionName, numAttributes_); fieldInfo_ = (TIFFFieldInfo**) malloc(numAttributes_ * sizeof(TIFFFieldInfo *)); if (fieldInfo_ == NULL) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s error, fieldInfo_ malloc failed. file: %s\n", driverName, functionName, fileName); return asynError; } for (int i=0; i<numAttributes_; ++i) { asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s Initializing %d fieldInfo_ entry.\n", driverName, functionName, i); fieldInfo_[i] = NULL; } asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s Looping over attributes...\n", driverName, functionName); pAttribute = this->pFileAttributes->next(NULL); while (pAttribute) { const char *attributeName = pAttribute->getName(); //const char *attributeDescription = pAttribute->getDescription(); const char *attributeSource = pAttribute->getSource(); asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s : attribute: %s, source: %s\n", driverName, functionName, attributeName, attributeSource); NDAttrDataType_t attrDataType; size_t attrSize; NDAttrValue value; pAttribute->getValueInfo(&attrDataType, &attrSize); memset(tagString, 0, MAX_ATTRIBUTE_STRING_SIZE); switch (attrDataType) { case NDAttrInt8: case NDAttrUInt8: case NDAttrInt16: case NDAttrUInt16: case NDAttrInt32: case NDAttrUInt32: { pAttribute->getValue(attrDataType, &value.i32); epicsSnprintf(tagString, MAX_ATTRIBUTE_STRING_SIZE, "%s:%d", attributeName, value.i32); break; } case NDAttrFloat32: { pAttribute->getValue(attrDataType, &value.f32); epicsSnprintf(tagString, MAX_ATTRIBUTE_STRING_SIZE, "%s:%f", attributeName, value.f32); break; } case NDAttrFloat64: { pAttribute->getValue(attrDataType, &value.f64); epicsSnprintf(tagString, MAX_ATTRIBUTE_STRING_SIZE, "%s:%f", attributeName, value.f64); break; } case NDAttrString: { memset(attrString, 0, MAX_ATTRIBUTE_STRING_SIZE); pAttribute->getValue(attrDataType, attrString, MAX_ATTRIBUTE_STRING_SIZE); epicsSnprintf(tagString, MAX_ATTRIBUTE_STRING_SIZE, "%s:%s", attributeName, attrString); break; } case NDAttrUndefined: break; default: asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s error, unknown attrDataType=%d\n", driverName, functionName, attrDataType); return asynError; break; } if (attrDataType != NDAttrUndefined) { asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s:%s : tagId: %d, tagString: %s\n", driverName, functionName, tagId, tagString); fieldInfo_[count] = (TIFFFieldInfo*) malloc(sizeof(TIFFFieldInfo)); populateAsciiFieldInfo(fieldInfo_[count], tagId, attributeName); TIFFMergeFieldInfo(output, fieldInfo_[count], 1); TIFFSetField(this->output, tagId, tagString); ++count; ++tagId; if ((tagId == TIFFTAG_END_) || (count > numAttributes_)) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s error, Too many tags/attributes for file. tagId: %d, count: %d\n", driverName, functionName, tagId, count); break; } } pAttribute = this->pFileAttributes->next(pAttribute); } return(asynSuccess); }