Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Applied bitsPerPixel.patch to bring in bitsPerPixel support from pcds… #314

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions ADApp/ADSrc/NDArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
NDArray::NDArray()
: referenceCount(0), pNDArrayPool(NULL),
uniqueId(0), timeStamp(0.0), ndims(0), dataType(NDInt8),
dataSize(0), pData(NULL)
dataSize(0), bitsPerElement(0), pData(NULL)
{
this->epicsTS.secPastEpoch = 0;
this->epicsTS.nsec = 0;
Expand Down Expand Up @@ -148,6 +148,7 @@ int NDArray::getInfo(NDArrayInfo_t *pInfo)
pInfo->ySize = this->dims[pInfo->yDim].size;
pInfo->colorSize = this->dims[pInfo->colorDim].size;
}
pInfo->bitsPerElement = this->bitsPerElement;
return(ND_SUCCESS);
}

Expand Down Expand Up @@ -201,8 +202,8 @@ int NDArray::report(FILE *fp, int details)
this->ndims);
for (dim=0; dim<this->ndims; dim++) fprintf(fp, "%d ", (int)this->dims[dim].size);
fprintf(fp, "]\n");
fprintf(fp, " dataType=%d, dataSize=%d, pData=%p\n",
this->dataType, (int)this->dataSize, this->pData);
fprintf(fp, " dataType=%d, bitsPerElement=%d, dataSize=%d, pData=%p\n",
this->dataType, this->bitsPerElement, (int)this->dataSize, this->pData);
fprintf(fp, " uniqueId=%d, timeStamp=%f, referenceCount=%d\n",
this->uniqueId, this->timeStamp, this->referenceCount);
fprintf(fp, " number of attributes=%d\n", this->pAttributeList->count());
Expand All @@ -212,3 +213,41 @@ int NDArray::report(FILE *fp, int details)
return ND_SUCCESS;
}

int GetNDColorModeBits( NDColorMode_t tyColor, NDDataType_t tyData )
{
int nBits;
switch ( tyColor )
{
default:
case NDColorModeMono:
nBits = GetNDDataTypeBits( tyData );
break;
// For defined color standards, set nBits to the
// number of combined bits in one pixel element
case NDColorModeBayer:
// Optimal packing uses all bits of data type
nBits = GetNDDataTypeBits( tyData );
break;
case NDColorModeRGB1:
case NDColorModeRGB2:
case NDColorModeRGB3:
// 3 pixels packed with room for a 4th
nBits = GetNDDataTypeBits( tyData ) * 3 / 4;
break;
case NDColorModeYUV444:
// 3 values for 1 pixel
nBits = 3 * GetNDDataTypeBits( tyData );
break;
case NDColorModeYUV422:
// 4 values for 2 pixels
nBits = 4 * GetNDDataTypeBits( tyData );
break;
case NDColorModeYUV411:
// 6 values for 4 pixels
nBits = 6 * GetNDDataTypeBits( tyData );
break;
}
return nBits;
}


8 changes: 6 additions & 2 deletions ADApp/ADSrc/NDArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ typedef enum
NDColorModeYUV411 /**< YUV image, 6 bytes encodes 4 RGB pixels */
} NDColorMode_t;

extern int GetNDColorModeBits( NDColorMode_t, NDDataType_t );

/** Enumeration of Bayer patterns for NDArray attribute "bayerPattern".
* This value is only meaningful if colorMode is NDColorModeBayer.
* This value is needed because the Bayer pattern will change when reading out a
Expand Down Expand Up @@ -68,7 +70,8 @@ typedef struct NDDimension {
/** Structure returned by NDArray::getInfo */
typedef struct NDArrayInfo {
size_t nElements; /**< The total number of elements in the array */
int bytesPerElement; /**< The number of bytes per element in the array */
int bitsPerElement; /**< The number of bits per element in the array */
int bytesPerElement; /**< The number of bytes per element in the array */
size_t totalBytes; /**< The total number of bytes required to hold the array;
* this may be less than NDArray::dataSize. */
/**< The following are mostly useful for color images (RGB1, RGB2, RGB3) */
Expand Down Expand Up @@ -115,6 +118,7 @@ class epicsShareClass NDArray {
NDDataType_t dataType; /**< Data type for this array. */
size_t dataSize; /**< Data size for this array; actual amount of memory allocated for *pData, may be more than
* required to hold the array*/
int bitsPerElement; /**< The number of bits per element in the array */
void *pData; /**< Pointer to the array data.
* The data is assumed to be stored in the order of dims[0] changing fastest, and
* dims[ndims-1] changing slowest. */
Expand Down Expand Up @@ -154,7 +158,7 @@ class epicsShareClass NDArrayPool {
epicsMutexId listLock_; /**< Mutex to protect the free list */
int maxBuffers_; /**< Maximum number of buffers this object is allowed to allocate; -1=unlimited */
int numBuffers_; /**< Number of buffers this object has currently allocated */
size_t maxMemory_; /**< Maximum bytes of memory this object is allowed to allocate; -1=unlimited */
size_t maxMemory_; /**< Maximum bytes of memory this object is allowed to allocate; 0=unlimited */
size_t memorySize_; /**< Number of bytes of memory this object has currently allocated */
int numFree_; /**< Number of NDArray objects in the free list */
};
Expand Down
15 changes: 15 additions & 0 deletions ADApp/ADSrc/NDArrayPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

#include <stdlib.h>
#include <math.h>

#include <cantProceed.h>
#include <epicsExport.h>
Expand Down Expand Up @@ -90,6 +91,7 @@ NDArray* NDArrayPool::alloc(int ndims, size_t *dims, NDDataType_t dataType, size
/* Initialize fields */
pArray->pNDArrayPool = this;
pArray->dataType = dataType;
pArray->bitsPerElement = GetNDDataTypeBits(dataType);
pArray->ndims = ndims;
memset(pArray->dims, 0, sizeof(pArray->dims));
for (i=0; i<ndims && i<ND_ARRAY_MAX_DIMS; i++) {
Expand Down Expand Up @@ -192,6 +194,7 @@ NDArray* NDArrayPool::copy(NDArray *pIn, NDArray *pOut, int copyData)
pOut = this->alloc(pIn->ndims, dimSizeOut, pIn->dataType, 0, NULL);
if(NULL==pOut) return NULL;
}
pOut->bitsPerElement = pIn->bitsPerElement;
pOut->uniqueId = pIn->uniqueId;
pOut->timeStamp = pIn->timeStamp;
pOut->epicsTS = pIn->epicsTS;
Expand Down Expand Up @@ -523,6 +526,18 @@ int NDArrayPool::convert(NDArray *pIn,
driverName, functionName);
return(ND_ERROR);
}

/* Use log2 of binning factors to calculate effect on bitsPerElement */
pOut->bitsPerElement = pIn->bitsPerElement;
size_t binFactor = 1;
for (i=0; i<pIn->ndims; i++)
binFactor *= dimsOutCopy[i].binning;
pOut->bitsPerElement += lround( log2( binFactor ) );

/* Clip bitsPerElement to max for output dataType */
if( pOut->bitsPerElement > GetNDDataTypeBits(pOut->dataType) )
pOut->bitsPerElement = GetNDDataTypeBits(pOut->dataType);

/* Copy fields from input to output */
pOut->timeStamp = pIn->timeStamp;
pOut->epicsTS = pIn->epicsTS;
Expand Down
25 changes: 25 additions & 0 deletions ADApp/ADSrc/NDAttribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,4 +451,29 @@ int NDAttribute::report(FILE *fp, int details)
return ND_SUCCESS;
}

/** Get the max number of bits per pixel for the specified data type
* \param[in] NDDataType_t Data type
*/
int GetNDDataTypeBits( NDDataType_t tyData )
{
int nBits;
switch ( tyData )
{
// Default to large number so conversions to
// integer data types will be clipped to max
default: nBits = 99; break;
case NDInt8: nBits = 8; break;
case NDUInt8: nBits = 8; break;
case NDInt16: nBits = 16; break;
case NDUInt16: nBits = 16; break;
case NDInt32: nBits = 32; break;
case NDUInt32: nBits = 32; break;
// nBits is more an indicator of max pixel value for mono rendering
// than a measure of accuracy, so we set floating point types to
// a large number to avoid clipping w/ wierd binning like 512x512
case NDFloat32: nBits = 99; break;
case NDFloat64: nBits = 99; break;
}
return nBits;
}

2 changes: 2 additions & 0 deletions ADApp/ADSrc/NDAttribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ typedef enum
NDFloat64 /**< 64-bit float */
} NDDataType_t;

extern int GetNDDataTypeBits( NDDataType_t );

/** Enumeration of NDAttribute attribute data types */
typedef enum
{
Expand Down
11 changes: 7 additions & 4 deletions ADApp/ADSrc/asynNDArrayDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ static const char *driverName = "asynNDArrayDriver";

/** Checks whether the directory specified exists.
*
* This is a convenience function that determines the directory specified exists.
* It adds a trailing '/' or '\' character to the path if one is not present.
* This is a convenience function that determines if the directory specified exists.
* It adds a trailing '/', (WIN32 '\'), character to the path if one is not present.
* It returns true if the directory exists and false if it does not
*/
bool asynNDArrayDriver::checkPath(std::string &filePath)
Expand Down Expand Up @@ -231,8 +231,8 @@ asynStatus asynNDArrayDriver::createFileName(int maxChars, char *fullFileName)
* \param[out] filePath The file path.
* \param[out] fileName The constructed file name without file file path.
*
* This is a convenience function that constructs a file path and file name
* from the NDFilePath, NDFileName, NDFileNumber, and
* This is a convenience function that constructs the directory path and the
* file name in that directory from the NDFilePath, NDFileName, NDFileNumber, and
* NDFileTemplate parameters. If NDAutoIncrement is true then it increments the
* NDFileNumber after creating the file name.
*/
Expand Down Expand Up @@ -720,6 +720,7 @@ asynNDArrayDriver::asynNDArrayDriver(const char *portName, int maxAddr, int maxB
createParam(NDNDimensionsString, asynParamInt32, &NDNDimensions);
createParam(NDDimensionsString, asynParamInt32, &NDDimensions);
createParam(NDDataTypeString, asynParamInt32, &NDDataType);
createParam(NDBitsPerPixelString, asynParamInt32, &NDBitsPerPixel);
createParam(NDColorModeString, asynParamInt32, &NDColorMode);
createParam(NDUniqueIdString, asynParamInt32, &NDUniqueId);
createParam(NDTimeStampString, asynParamFloat64, &NDTimeStamp);
Expand Down Expand Up @@ -777,6 +778,8 @@ asynNDArrayDriver::asynNDArrayDriver(const char *portName, int maxAddr, int maxB
setIntegerParam(NDArraySizeZ, 0);
setIntegerParam(NDArraySize, 0);
setIntegerParam(NDNDimensions, 0);
setIntegerParam(NDDataType, NDUInt8);
setIntegerParam(NDBitsPerPixel, 8);
setIntegerParam(NDColorMode, NDColorModeMono);
setIntegerParam(NDUniqueId, 0);
setDoubleParam (NDTimeStamp, 0.);
Expand Down
2 changes: 2 additions & 0 deletions ADApp/ADSrc/asynNDArrayDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ typedef enum {
#define NDNDimensionsString "ARRAY_NDIMENSIONS" /**< (asynInt32, r/o) Number of dimensions in array */
#define NDDimensionsString "ARRAY_DIMENSIONS" /**< (asynInt32Array, r/o) Array dimensions */
#define NDDataTypeString "DATA_TYPE" /**< (asynInt32, r/w) Data type (NDDataType_t) */
#define NDBitsPerPixelString "BITS_PER_PIXEL" /**< (asynInt32, r/w) Number of bits per pixel */
#define NDColorModeString "COLOR_MODE" /**< (asynInt32, r/w) Color mode (NDColorMode_t) */
#define NDUniqueIdString "UNIQUE_ID" /**< (asynInt32, r/o) Unique ID number of array */
#define NDTimeStampString "TIME_STAMP" /**< (asynFloat64, r/o) Time stamp of array */
Expand Down Expand Up @@ -143,6 +144,7 @@ class epicsShareFunc asynNDArrayDriver : public asynPortDriver {
int NDNDimensions;
int NDDimensions;
int NDDataType;
int NDBitsPerPixel;
int NDColorMode;
int NDUniqueId;
int NDTimeStamp;
Expand Down
7 changes: 7 additions & 0 deletions ADApp/Db/NDArrayBase.template
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,13 @@ record(mbbi, "$(P)$(R)DataType_RBV")
field(SCAN, "I/O Intr")
}

record(longin, "$(P)$(R)BitsPerPixel_RBV")
{
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1))BITS_PER_PIXEL")
field(SCAN, "I/O Intr")
}

###################################################################
# These records control the color mode #
# These choices must agree with NDColorMode_t in NDArray.h #
Expand Down
8 changes: 7 additions & 1 deletion ADApp/pluginSrc/NDPluginColorConvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,12 @@ void NDPluginColorConvert::convertColor(NDArray *pArray)
default:
break;
}

if ( pArrayOut ) {
/* Set nBits based on total bits used to represent one pixel element. */
pArrayOut->bitsPerElement = GetNDColorModeBits( colorModeOut, pArrayOut->dataType );
}

/* If the output array pointer is null then no conversion was done, copy the input to the output */
if (!pArrayOut) pArrayOut = this->pNDArrayPool->copy(pArray, NULL, 1);
this->lock();
Expand Down Expand Up @@ -569,7 +575,7 @@ void NDPluginColorConvert::processCallbacks(NDArray *pArray)
driverName, functionName, pArray->dataType);
break;
}

callParamCallbacks();
}

Expand Down
27 changes: 16 additions & 11 deletions ADApp/pluginSrc/NDPluginDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ NDPluginDriver::~NDPluginDriver()
* This method takes care of some bookkeeping for callbacks, updating parameters
* from data in the class and in the NDArray. It does asynInt32Array callbacks
* for the dimensions array if the dimensions of the NDArray data have changed. */
void NDPluginDriver::beginProcessCallbacks(NDArray *pArray)
void NDPluginDriver::beginProcessCallbacks(NDArray *pArray)
{
int arrayCounter;
int i, dimsChanged;
Expand All @@ -200,19 +200,24 @@ NDPluginDriver::~NDPluginDriver()
if (pAttribute) pAttribute->getValue(NDAttrInt32, &colorMode);
pAttribute = pArray->pAttributeList->find("BayerPattern");
if (pAttribute) pAttribute->getValue(NDAttrInt32, &bayerPattern);

getIntegerParam(NDArrayCounter, &arrayCounter);
arrayCounter++;
setIntegerParam(NDArrayCounter, arrayCounter);
setIntegerParam(NDNDimensions, pArray->ndims);
setIntegerParam(NDDataType, pArray->dataType);
setIntegerParam(NDColorMode, colorMode);
setIntegerParam(NDBayerPattern, bayerPattern);
setIntegerParam(NDUniqueId, pArray->uniqueId);
setIntegerParam(NDArrayCounter, arrayCounter);
setIntegerParam(NDNDimensions, pArray->ndims);
setIntegerParam(NDDataType, pArray->dataType);

NDArrayInfo_t arrayInfo;
pArray->getInfo(&arrayInfo);
setIntegerParam(NDBitsPerPixel, arrayInfo.bitsPerElement);

setIntegerParam(NDColorMode, colorMode);
setIntegerParam(NDBayerPattern, bayerPattern);
setIntegerParam(NDUniqueId, pArray->uniqueId);
setTimeStamp(&pArray->epicsTS);
setDoubleParam(NDTimeStamp, pArray->timeStamp);
setIntegerParam(NDEpicsTSSec, pArray->epicsTS.secPastEpoch);
setIntegerParam(NDEpicsTSNsec, pArray->epicsTS.nsec);
setDoubleParam(NDTimeStamp, pArray->timeStamp);
setIntegerParam(NDEpicsTSSec, pArray->epicsTS.secPastEpoch);
setIntegerParam(NDEpicsTSNsec, pArray->epicsTS.nsec);
/* See if the array dimensions have changed. If so then do callbacks on them. */
for (i=0, dimsChanged=0; i<ND_ARRAY_MAX_DIMS; i++) {
size = (int)pArray->dims[i].size;
Expand Down
13 changes: 13 additions & 0 deletions ADApp/pluginSrc/NDPluginProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,19 @@ void NDPluginProcess::processCallbacks(NDArray *pArray)
this->pNDArrayPool->convert(pScratch, &pArrayOut, (NDDataType_t)dataType);
}

if (enableOffsetScale && (NULL != pArrayOut)) {
/* Update bitsPerElement */
int bitsPerElement = arrayInfo.bitsPerElement;
bitsPerElement += static_cast<int>( ceil( log2( scale ) ) );

/* Clip bitsPerElement to max for output dataType */
if( bitsPerElement > GetNDDataTypeBits(pArrayOut->dataType) )
bitsPerElement = GetNDDataTypeBits(pArrayOut->dataType);

/* Set the bits per pixel of the ROI output */
pArrayOut->bitsPerElement = bitsPerElement;
}

if (autoOffsetScale && (NULL != pArrayOut)) {
pArrayOut->getInfo(&arrayInfo);
double maxScale = pow(2., arrayInfo.bytesPerElement*8) - 1;
Expand Down
21 changes: 19 additions & 2 deletions ADApp/pluginSrc/NDPluginROI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ void NDPluginROI::processCallbacks(NDArray *pArray)

/* Extract this ROI from the input array. The convert() function allocates
* a new array and it is reserved (reference count = 1) */
if (dataType == -1) dataType = (int)pArray->dataType;
if (dataType == -1) {
dataType = (int)pArray->dataType;
}
/* We treat the case of RGB1 data specially, so that NX and NY are the X and Y dimensions of the
* image, not the first 2 dimensions. This makes it much easier to switch back and forth between
* RGB1 and mono mode when using an ROI. */
Expand Down Expand Up @@ -178,7 +180,7 @@ void NDPluginROI::processCallbacks(NDArray *pArray)
for (i=0; i<scratchInfo.nElements; i++) pData[i] = pData[i]/scale;
this->pNDArrayPool->convert(pScratch, &pOutput, (NDDataType_t)dataType);
pScratch->release();
}
}
else {
this->pNDArrayPool->convert(pArray, &pOutput, (NDDataType_t)dataType, dims);
}
Expand Down Expand Up @@ -223,6 +225,21 @@ void NDPluginROI::processCallbacks(NDArray *pArray)
}
}
this->lock();

/* Calculate ROI bitsPerElement */
double bitsPerPixel = arrayInfo.bitsPerElement;
size_t binFactor = 1;
for ( size_t iDim=0; iDim < static_cast<unsigned>(pArray->ndims); iDim++ )
binFactor *= dims[iDim].binning;
if ( binFactor != 1 )
bitsPerPixel += log2( binFactor );
if ( enableScale && scale != 0 && scale != 1 )
bitsPerPixel -= log2( scale );
/* Clip bitsPerElement to max for output dataType */
if( bitsPerPixel > GetNDDataTypeBits(pOutput->dataType) )
bitsPerPixel = GetNDDataTypeBits(pOutput->dataType);
/* Set the bits per pixel of the ROI output */
pOutput->bitsPerElement = lrint( bitsPerPixel );

/* Set the image size of the ROI image data */
setIntegerParam(NDArraySizeX, 0);
Expand Down
Loading