diff --git a/ADApp/Db/Makefile b/ADApp/Db/Makefile index 79162b39c..0f45ae32b 100644 --- a/ADApp/Db/Makefile +++ b/ADApp/Db/Makefile @@ -52,6 +52,7 @@ DB += NDAttrPlotAttr.template DB += NDAttrPlotData.template DB += NDAttrPlot.template DB += NDCodec.template +DB += NDFileTIFFS3.template #---------------------------------------------------- # If .db template is not named *.template add diff --git a/ADApp/Db/NDFileTIFFS3.template b/ADApp/Db/NDFileTIFFS3.template new file mode 100755 index 000000000..6719c4271 --- /dev/null +++ b/ADApp/Db/NDFileTIFFS3.template @@ -0,0 +1,7 @@ +#=================================================================# +# Template file: NDFileTIFFS3.template +# Database for NDFileTIFFS3 driver, which saves NDArray data +# in the TIFF file format + +include "NDFileTIFF.template" +include "NDPluginBase.template" diff --git a/ADApp/Db/NDFileTIFFS3_settings.req b/ADApp/Db/NDFileTIFFS3_settings.req new file mode 100644 index 000000000..44b2729d5 --- /dev/null +++ b/ADApp/Db/NDFileTIFFS3_settings.req @@ -0,0 +1 @@ +file "NDPluginFile_settings.req", P=$(P), R=$(R) diff --git a/ADApp/commonDriverMakefile b/ADApp/commonDriverMakefile index 67c14780b..5ea8d9fc3 100644 --- a/ADApp/commonDriverMakefile +++ b/ADApp/commonDriverMakefile @@ -262,6 +262,26 @@ ifdef ADPLUGINCENTROIDS PROD_LIBS += NDPluginCentroids centroids endif +ifeq ($(WITH_TIFFS3),YES) + $(DBD_NAME)_DBD += NDFileTIFFS3.dbd + ifeq ($(TIFFS3_EXTERNAL),NO) + PROD_LIBS += tiff + else + ifdef TIFFS3_LIB + tiff_DIR = $(TIFF_LIB) + PROD_LIBS += tiff + else + PROD_SYS_LIBS += tiff + PROD_SYS_LIBS += tiffxx + PROD_SYS_LIBS += aws-cpp-sdk-s3 + PROD_SYS_LIBS += aws-cpp-sdk-core + PROD_SYS_LIBS += aws-c-event-stream + PROD_SYS_LIBS += aws-c-common + PROD_SYS_LIBS += aws-checksums + endif + endif +endif + # Required modules $(DBD_NAME)_DBD += asyn.dbd PROD_LIBS += asyn diff --git a/ADApp/pluginSrc/Makefile b/ADApp/pluginSrc/Makefile index ebf5bdd06..3c2622dfa 100644 --- a/ADApp/pluginSrc/Makefile +++ b/ADApp/pluginSrc/Makefile @@ -189,6 +189,19 @@ ifeq ($(WITH_BITSHUFFLE), YES) USR_CXXFLAGS += -DHAVE_BITSHUFFLE endif +ifeq ($(WITH_TIFFS3),YES) + DBD += NDFileTIFFS3.dbd + INC += NDFileTIFFS3.h + LIB_SRCS += NDFileTIFFS3.cpp + ifeq ($(SHARED_LIBRARIES),NO) + # This flag is used to indicate that the TIFF library was built statically + USR_CXXFLAGS_WIN32 += -DLIBTIFF_STATIC + endif + ifdef TIFFS3_INCLUDE + USR_INCLUDES += $(addprefix -I, $(TIFFS3_INCLUDE)) + endif +endif + ifdef BLOSC_INCLUDE USR_INCLUDES += $(addprefix -I, $(BLOSC_INCLUDE)) endif diff --git a/ADApp/pluginSrc/NDFileTIFF.h b/ADApp/pluginSrc/NDFileTIFF.h index 6173b1f56..48369e86e 100644 --- a/ADApp/pluginSrc/NDFileTIFF.h +++ b/ADApp/pluginSrc/NDFileTIFF.h @@ -33,13 +33,12 @@ class epicsShareClass NDFileTIFF : public NDPluginFile { virtual asynStatus writeFile(NDArray *pArray); virtual asynStatus closeFile(); -private: +protected: TIFF *tiff; NDColorMode_t colorMode; - int *pAttributeId; NDAttributeList *pFileAttributes; int numAttributes_; - + int *pAttributeId; }; #endif diff --git a/ADApp/pluginSrc/NDFileTIFFS3.cpp b/ADApp/pluginSrc/NDFileTIFFS3.cpp new file mode 100755 index 000000000..b4bf17fea --- /dev/null +++ b/ADApp/pluginSrc/NDFileTIFFS3.cpp @@ -0,0 +1,532 @@ +/* NDFileTIFFS3.cpp + * Writes NDArrays to TIFF files on S3 Storage + * + * Stuart B. Wilkins + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "NDPluginFile.h" +#include "NDFileTIFF.h" +#include "NDFileTIFFS3.h" + +#define STRING_BUFFER_SIZE 2048 + +static const char *driverName = "NDFileTIFF"; + +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 int TIFFTAG_FIRST_ATTRIBUTE = 65010; +static const int TIFFTAG_LAST_ATTRIBUTE = 65535; + +#define NUM_CUSTOM_TIFF_TAGS (4 + TIFFTAG_LAST_ATTRIBUTE - TIFFTAG_FIRST_ATTRIBUTE + 1) + +static TIFFFieldInfo tiffFieldInfo[NUM_CUSTOM_TIFF_TAGS] = { + {TIFFTAG_NDTIMESTAMP, 1, 1, TIFF_DOUBLE,FIELD_CUSTOM, 1, 0, (char *)"NDTimeStamp"}, + {TIFFTAG_UNIQUEID, 1, 1, TIFF_LONG,FIELD_CUSTOM, 1, 0, (char *)"NDUniqueId"}, + {TIFFTAG_EPICSTSSEC, 1, 1, TIFF_LONG,FIELD_CUSTOM, 1, 0, (char *)"EPICSTSSec"}, + {TIFFTAG_EPICSTSNSEC, 1, 1, TIFF_LONG,FIELD_CUSTOM, 1, 0, (char *)"EPICSTSNsec"} +}; + +static void registerCustomTIFFTags(TIFF *tif) +{ + /* Install the extended Tag field info */ + TIFFMergeFieldInfo(tif, tiffFieldInfo, sizeof(tiffFieldInfo)/sizeof(tiffFieldInfo[0])); +} + +static void augmentLibTiffWithCustomTags() { + static bool first_time = true; + if (!first_time) return; + first_time = false; + TIFFSetTagExtender(registerCustomTIFFTags); +} + +/** 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 NDFileTIFFS3::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[STRING_BUFFER_SIZE] = {0}; + char attrString[STRING_BUFFER_SIZE] = {0}; + char tagName[STRING_BUFFER_SIZE] = {0}; + int i; + TIFFFieldInfo fieldInfo = {0, 1, 1, TIFF_ASCII, FIELD_CUSTOM, 1, 0, tagName}; + + for (i=TIFFTAG_FIRST_ATTRIBUTE; i<=TIFFTAG_LAST_ATTRIBUTE; i++) { + sprintf(tagName, "Attribute_%d", i-TIFFTAG_FIRST_ATTRIBUTE+1); + fieldInfo.field_tag = i; + tiffFieldInfo[4+i-TIFFTAG_FIRST_ATTRIBUTE] = fieldInfo; + } + + augmentLibTiffWithCustomTags(); + + /* Suppress error and warning messages from the TIFF library */ + TIFFSetErrorHandler(NULL); + TIFFSetWarningHandler(NULL); + + /* We don't support opening an existing file for appending yet */ + if (openMode != NDFileModeWrite) { + return(asynError); + } + + // Now do AMAZON S3 Stuff + awsStream = Aws::MakeShared(""); + strncpy(keyName, fileName, 255); + + if ((this->tiff = TIFFStreamOpen("TIFF", (std::ostream*)awsStream.get())) == NULL) + { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, + "%s:%s error opening file %s\n", + driverName, functionName, fileName); + return (asynError); + } + asynPrint(pasynUserSelf, ASYN_TRACE_FLOW, + "%s::%s opened file %s\n", + driverName, functionName, fileName); + + /* 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 NDInt64: + sampleFormat = SAMPLEFORMAT_INT; + bitsPerSample = 64; + break; + case NDUInt64: + sampleFormat = SAMPLEFORMAT_UINT; + bitsPerSample = 64; + break; + case NDFloat32: + sampleFormat = SAMPLEFORMAT_IEEEFP; + bitsPerSample = 32; + break; + case NDFloat64: + sampleFormat = SAMPLEFORMAT_IEEEFP; + bitsPerSample = 64; + break; + } + if (pArray->ndims == 1) { + sizeX = pArray->dims[0].size; + sizeY = 1; + rowsPerStrip = sizeY; + samplesPerPixel = 1; + photoMetric = PHOTOMETRIC_MINISBLACK; + planarConfig = PLANARCONFIG_CONTIG; + this->colorMode = NDColorModeMono; + } else 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); + } + + TIFFSetField(this->tiff, TIFFTAG_NDTIMESTAMP, pArray->timeStamp); + TIFFSetField(this->tiff, TIFFTAG_UNIQUEID, pArray->uniqueId); + TIFFSetField(this->tiff, TIFFTAG_EPICSTSSEC, pArray->epicsTS.secPastEpoch); + TIFFSetField(this->tiff, TIFFTAG_EPICSTSNSEC, pArray->epicsTS.nsec); + TIFFSetField(this->tiff, TIFFTAG_BITSPERSAMPLE, bitsPerSample); + TIFFSetField(this->tiff, TIFFTAG_SAMPLEFORMAT, sampleFormat); + TIFFSetField(this->tiff, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel); + TIFFSetField(this->tiff, TIFFTAG_PHOTOMETRIC, photoMetric); + TIFFSetField(this->tiff, TIFFTAG_PLANARCONFIG, planarConfig); + TIFFSetField(this->tiff, TIFFTAG_IMAGEWIDTH, (epicsUInt32)sizeX); + TIFFSetField(this->tiff, TIFFTAG_IMAGELENGTH, (epicsUInt32)sizeY); + TIFFSetField(this->tiff, 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, sizeof(tagString)-1); + TIFFSetField(this->tiff, TIFFTAG_MODEL, tagString); + } else { + TIFFSetField(this->tiff, TIFFTAG_MODEL, "Unknown"); + } + + pAttribute = this->pFileAttributes->find("Manufacturer"); + if (pAttribute) { + pAttribute->getValue(NDAttrString, tagString); + TIFFSetField(this->tiff, TIFFTAG_MAKE, tagString, sizeof(tagString)-1); + } else { + TIFFSetField(this->tiff, TIFFTAG_MAKE, "Unknown"); + } + + TIFFSetField(this->tiff, TIFFTAG_SOFTWARE, "EPICS areaDetector"); + + // If the attribute TIFFImageDescription exists use it to set the TIFFTAG_IMAGEDESCRIPTION + pAttribute = this->pFileAttributes->find("TIFFImageDescription"); + if (pAttribute) { + pAttribute->getValue(NDAttrString, tagString, sizeof(tagString)-1); + TIFFSetField(this->tiff, TIFFTAG_IMAGEDESCRIPTION, tagString); + } + + int count = 0; + int tagId = TIFFTAG_FIRST_ATTRIBUTE; + + numAttributes_ = this->pFileAttributes->count(); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, + "%s:%s this->pFileAttributes->count(): %d\n", + driverName, functionName, numAttributes_); + + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, + "%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_TRACEIO_DRIVER, + "%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, sizeof(tagString)); + + switch (attrDataType) { + case NDAttrInt8: + case NDAttrUInt8: + case NDAttrInt16: + case NDAttrUInt16: + case NDAttrInt32: + case NDAttrUInt32: + case NDAttrInt64: + case NDAttrUInt64: { + pAttribute->getValue(attrDataType, &value.i64); + epicsSnprintf(tagString, sizeof(tagString)-1, "%s:%lld", attributeName, value.i64); + break; + } + case NDAttrFloat32: { + pAttribute->getValue(attrDataType, &value.f32); + epicsSnprintf(tagString, sizeof(tagString)-1, "%s:%f", attributeName, value.f32); + break; + } + case NDAttrFloat64: { + pAttribute->getValue(attrDataType, &value.f64); + epicsSnprintf(tagString, sizeof(tagString)-1, "%s:%f", attributeName, value.f64); + break; + } + case NDAttrString: { + memset(attrString, 0, sizeof(tagString)-1); + pAttribute->getValue(attrDataType, attrString, sizeof(attrString)-1); + epicsSnprintf(tagString, sizeof(tagString)-1, "%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_TRACEIO_DRIVER, + "%s:%s : tagId: %d, tagString: %s\n", + driverName, functionName, tagId, tagString); + TIFFSetField(this->tiff, tagId, tagString); + ++count; + ++tagId; + if ((tagId > TIFFTAG_LAST_ATTRIBUTE) || (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); +} + +void NDFileTIFFS3::PutObjectAsyncFinished(const Aws::S3::S3Client* s3Client, + const Aws::S3::Model::PutObjectRequest& request, + const Aws::S3::Model::PutObjectOutcome& outcome, + const std::shared_ptr& context) +{ + std::shared_ptr __ctx(context); + std::shared_ptr _ctx = + std::dynamic_pointer_cast(__ctx); + std::shared_ptr ctx = std::const_pointer_cast(_ctx); + + ctx->GetTIFFS3()->putObjectFinished(outcome); +} + +void NDFileTIFFS3::putObjectFinished(const Aws::S3::Model::PutObjectOutcome& outcome) +{ + const char* functionName = "NDFileTIFFS3::putObjectFinished"; + if (!outcome.IsSuccess()) { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, + "%s:%s error, AWS S3 Error : %s\n", + driverName, functionName, outcome.GetError().GetMessage().c_str()); + } + this->callParamCallbacks(); +} + + +asynStatus NDFileTIFFS3::closeFile() +{ + NDFileTIFF::closeFile(); + + Aws::S3::Model::PutObjectRequest objectRequest; + objectRequest.SetBucket(""); + objectRequest.SetKey(keyName); + objectRequest.SetBody(awsStream); + + std::shared_ptr context = + Aws::MakeShared("PutObjectAllocationTag"); + context->SetUUID(keyName); + context->SetTIFFS3(this); + s3Client->PutObjectAsync(objectRequest, NDFileTIFFS3::PutObjectAsyncFinished, context); + + return asynSuccess; +} + +/** Constructor for NDFileTIFFS3; all parameters are simply passed to NDPluginFile::NDPluginFile. + * \param[in] portName The name of the asyn port driver to be created. + * \param[in] queueSize The number of NDArrays that the input queue for this plugin can hold when + * NDPluginDriverBlockingCallbacks=0. Larger queues can decrease the number of dropped arrays, + * at the expense of more NDArray buffers being allocated from the underlying driver's NDArrayPool. + * \param[in] blockingCallbacks Initial setting for the NDPluginDriverBlockingCallbacks flag. + * 0=callbacks are queued and executed by the callback thread; 1 callbacks execute in the thread + * of the driver doing the callbacks. + * \param[in] NDArrayPort Name of asyn port driver for initial source of NDArray callbacks. + * \param[in] NDArrayAddr asyn port driver address for initial source of NDArray callbacks. + * \param[in] priority The thread priority for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags. + * \param[in] stackSize The stack size for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags. + */ +NDFileTIFFS3::NDFileTIFFS3(const char *portName, int queueSize, int blockingCallbacks, + const char *NDArrayPort, int NDArrayAddr, + const char *endpoint, int awslog, int priority, int stackSize) + /* Invoke the base class constructor. + * We allocate 2 NDArrays of unlimited size in the NDArray pool. + * This driver can block (because writing a file can be slow), and it is not multi-device. + * Set autoconnect to 1. priority and stacksize can be 0, which will use defaults. */ + : NDFileTIFF(portName, queueSize, blockingCallbacks, + NDArrayPort, NDArrayAddr, priority, stackSize) +{ + //static const char *functionName = "NDFileTIFF"; + + /* Set the plugin type string */ + setStringParam(NDPluginDriverPluginType, "NDFileTIFFS3"); + this->supportsMultipleArrays = 0; + + if (awslog) + { + Aws::Utils::Logging::LogLevel level; + switch (awslog) + { + case 0: + level = Aws::Utils::Logging::LogLevel::Off; + break; + case 1: + level = Aws::Utils::Logging::LogLevel::Fatal; + break; + case 2: + level = Aws::Utils::Logging::LogLevel::Error; + break; + case 3: + level = Aws::Utils::Logging::LogLevel::Warn; + break; + case 4: + level = Aws::Utils::Logging::LogLevel::Info; + break; + case 5: + level = Aws::Utils::Logging::LogLevel::Debug; + break; + case 6: + level = Aws::Utils::Logging::LogLevel::Trace; + break; + default: + level = Aws::Utils::Logging::LogLevel::Off; + break; + } + Aws::Utils::Logging::InitializeAWSLogging( + Aws::MakeShared( + "NDFileTIFFS3", level, "NDFileTIFFS3_")); + awsLogging = true; + } else { + awsLogging = false; + } + + Aws::InitAPI(options); + + Aws::Client::ClientConfiguration config; + if (endpoint && endpoint[0]) + { + config.endpointOverride = endpoint; + } + config.verifySSL = false; + + s3Client = std::make_shared(config); +} + +NDFileTIFFS3::~NDFileTIFFS3() +{ + ShutdownAPI(options); + if (awsLogging) + { + Aws::Utils::Logging::ShutdownAWSLogging(); + } +} + +/* Configuration routine. Called directly, or from the iocsh */ + +extern "C" int NDFileTIFFS3Configure(const char *portName, int queueSize, int blockingCallbacks, + const char *NDArrayPort, int NDArrayAddr, + const char *endpoint, int awslog, int priority, int stackSize) +{ + // Stack size must be a minimum of 40000 on vxWorks because of automatic variables in NDFileTIFF::openFile() + #ifdef vxWorks + if (stackSize < 40000) stackSize = 40000; + #endif + NDFileTIFFS3 *pPlugin = new NDFileTIFFS3(portName, queueSize, blockingCallbacks, NDArrayPort, NDArrayAddr, + endpoint, awslog, priority, stackSize); + return pPlugin->start(); +} + + +/* EPICS iocsh shell commands */ + +static const iocshArg initArg0 = { "portName",iocshArgString}; +static const iocshArg initArg1 = { "frame queue size",iocshArgInt}; +static const iocshArg initArg2 = { "blocking callbacks",iocshArgInt}; +static const iocshArg initArg3 = { "NDArray Port",iocshArgString}; +static const iocshArg initArg4 = { "NDArray Addr",iocshArgInt}; +static const iocshArg initArg5 = { "endpoint",iocshArgString}; +static const iocshArg initArg6 = { "awslog",iocshArgInt}; +static const iocshArg initArg7 = { "priority",iocshArgInt}; +static const iocshArg initArg8 = { "stack size",iocshArgInt}; +static const iocshArg * const initArgs[] = {&initArg0, + &initArg1, + &initArg2, + &initArg3, + &initArg4, + &initArg5, + &initArg6, + &initArg7, + &initArg8}; +static const iocshFuncDef initFuncDef = {"NDFileTIFFS3Configure",9,initArgs}; +static void initCallFunc(const iocshArgBuf *args) +{ + NDFileTIFFS3Configure(args[0].sval, args[1].ival, args[2].ival, args[3].sval, + args[4].ival, args[5].sval, args[6].ival, args[7].ival, + args[8].ival); +} + +extern "C" void NDFileTIFFS3Register(void) +{ + iocshRegister(&initFuncDef,initCallFunc); +} + +extern "C" { +epicsExportRegistrar(NDFileTIFFS3Register); +} diff --git a/ADApp/pluginSrc/NDFileTIFFS3.dbd b/ADApp/pluginSrc/NDFileTIFFS3.dbd new file mode 100644 index 000000000..4a35c66c3 --- /dev/null +++ b/ADApp/pluginSrc/NDFileTIFFS3.dbd @@ -0,0 +1 @@ +registrar("NDFileTIFFS3Register") diff --git a/ADApp/pluginSrc/NDFileTIFFS3.h b/ADApp/pluginSrc/NDFileTIFFS3.h new file mode 100755 index 000000000..c9be3af63 --- /dev/null +++ b/ADApp/pluginSrc/NDFileTIFFS3.h @@ -0,0 +1,69 @@ +/* + * NDFileTIFF.h + * Writes NDArrays to TIFF files. + * John Hammonds + * April 17, 2009 + */ + +#ifndef DRV_NDFileTIFFS3_H +#define DRV_NDFileTIFFS3_H + +#include "NDFileTIFF.h" + +/** Writes NDArrays in the TIFF file format. To an Amazon S3 + Tagged Image File Format is a file format for storing images. The format was originally created by Aldus corporation and is + currently developed by Adobe Systems Incorporated. This plugin was developed using the libtiff library to write the file. + The current version is only capable of writing 2-D images with one image per file. + */ + +class epicsShareClass NDFileTIFFS3 : public NDFileTIFF { + public: + NDFileTIFFS3(const char *portName, int queueSize, int blockingCallbacks, + const char *NDArrayPort, int NDArrayAddr, + const char *endpoint, int awslog, + int priority, int stackSize); + + virtual ~NDFileTIFFS3(); + virtual asynStatus openFile(const char *fileName, NDFileOpenMode_t openMode, NDArray *pArray); + virtual asynStatus closeFile(); + + // Note: The following need to be static to deal with the callback being out of the + // scope of the class + static void PutObjectAsyncFinished(const Aws::S3::S3Client* s3Client, + const Aws::S3::Model::PutObjectRequest& request, + const Aws::S3::Model::PutObjectOutcome& outcome, + const std::shared_ptr& context); + void putObjectFinished(const Aws::S3::Model::PutObjectOutcome& outcome); + + private: + + Aws::SDKOptions options; + std::shared_ptr awsStream; + std::shared_ptr s3Client; + char keyName[256]; + bool awsLogging = false; +// +// /* The methods that this class implements */ +// virtual asynStatus readFile(NDArray **pArray); +// virtual asynStatus writeFile(NDArray *pArray); +// virtual asynStatus closeFile(); +// +}; + +class NDFileTIFFS3_AWSContext : public Aws::Client::AsyncCallerContext { + public: + NDFileTIFFS3_AWSContext() + : Aws::Client::AsyncCallerContext() {} + + void SetTIFFS3(NDFileTIFFS3 *c) { + tiffS3 = c; + } + NDFileTIFFS3* GetTIFFS3(void) { + return tiffS3; + } + private: + NDFileTIFFS3 *tiffS3; +}; + + +#endif