diff --git a/README.md b/README.md
index c871369..21083c1 100755
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ and ensure the following is uncommented:
```
# Optional: load NDPluginBar plugin
-NDBarConfigure("BAR1", $(QSIZE), 0, "$(PORT)", 0, 0, 0, 0)
+NDBarConfigure("BAR1", $(QSIZE), 0, "$(PORT)", 0, 0, 0, 0, 0, (MAX_THREADS=5))
dbLoadRecords("$(ADPLUGINBAR)/db/NDBar.template", "P=$(PREFIX),R=Bar1:, PORT=BAR1,ADDR=0,TIMEOUT=1,NDARRAY_PORT=$(PORT)")
set_requestfile_path("$(ADPLUGINBAR)/barApp/Db")
```
diff --git a/RELEASE.md b/RELEASE.md
index 6d43161..c4c6260 100755
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -11,6 +11,17 @@ files respectively, in the configure/ directory of the appropriate release of th
Release Notes
=============
+R2-2 (5-July-2019)
+----
+* Features Added:
+ * Support for maxThreads as used with other ADPlugins
+* Bug Fixes/Improvements
+ * Removed addAttribute call for data type
+ * Edit to use endProcessCallbacks instead of doCallbacksGenericPointer
+ * Doc/comments edited
+* Possible future plans
+ * PV for toggling image callbacks - Performance improvement and image view not always needed.
+
R2-1 (8-May-2019)
----
* Features Added:
diff --git a/barApp/barSrc/NDPluginBar.cpp b/barApp/barSrc/NDPluginBar.cpp
index 389698b..b7db2f5 100755
--- a/barApp/barSrc/NDPluginBar.cpp
+++ b/barApp/barSrc/NDPluginBar.cpp
@@ -38,6 +38,7 @@ using namespace zbar;
static const char *driverName = "NDPluginBar";
+
//------------------------------------------------------
// Functions called at init
//------------------------------------------------------
@@ -69,6 +70,7 @@ asynStatus NDPluginBar::initPVArrays() {
return asynSuccess;
}
+
//------------------------------------------------------
// Utility functions for printing errors and for clearing previous codes
//------------------------------------------------------
@@ -89,6 +91,7 @@ asynStatus NDPluginBar::clearPreviousCodes() {
return asynSuccess;
}
+
//------------------------------------------------------
// Image type conversion functions
//------------------------------------------------------
@@ -153,6 +156,7 @@ asynStatus NDPluginBar::ndArray2Mat(NDArray *pArray, NDArrayInfo *arrayInfo, Mat
return asynSuccess;
}
+
/**
* Function that converts Mat back into NDArray. This function is guaranteed to
* have either a 8 bit or 16 bit color image, because the bounding boxes drawn
@@ -165,30 +169,6 @@ asynStatus NDPluginBar::ndArray2Mat(NDArray *pArray, NDArrayInfo *arrayInfo, Mat
*/
asynStatus NDPluginBar::mat2NDArray(NDArray *pScratch, Mat &img) {
const char *functionName = "mat2NDArray";
- int ndims = 3;
- Size matSize = img.size();
- NDDataType_t dataType;
- NDColorMode_t colorMode = NDColorModeRGB1;
- size_t dims[ndims];
- dims[0] = 3;
- dims[1] = matSize.width;
- dims[2] = matSize.height;
-
- if (img.depth() == CV_8U)
- dataType = NDUInt8;
- else if (img.depth() == CV_8S)
- dataType = NDInt8;
- else if (img.depth() == CV_16U)
- dataType = NDUInt16;
- else if (img.depth() == CV_16S)
- dataType = NDInt16;
-
- pScratch = pNDArrayPool->alloc(ndims, dims, dataType, 0, NULL);
- if (pScratch == NULL) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error, unable to allocate array\n", driverName, functionName);
- img.release();
- return asynError;
- }
NDArrayInfo arrayInfo;
pScratch->getInfo(&arrayInfo);
@@ -202,17 +182,12 @@ asynStatus NDPluginBar::mat2NDArray(NDArray *pScratch, Mat &img) {
}
memcpy((unsigned char *)pScratch->pData, (unsigned char *)img.data, dataSize);
- pScratch->pAttributeList->add("ColorMode", "Color Mode", NDAttrInt32, &colorMode);
- pScratch->pAttributeList->add("DataType", "Data Type", NDAttrInt32, &dataType);
- getAttributes(pScratch->pAttributeList);
- doCallbacksGenericPointer(pScratch, NDArrayData, 0);
- //release the array
- pScratch->release();
// now that data is copied to NDArray, we don't need mat anymore
img.release();
return asynSuccess;
}
+
/**
* Function used to use a form of thresholding to reverse the coloration of a bar code
* or QR code that is in the white on black format rather than the standard black on white
@@ -229,6 +204,7 @@ asynStatus NDPluginBar::fix_inverted(Mat &img) {
return asynSuccess;
}
+
/**
* Function that is used simply to offload the process of setting the PV values
* of the detected corners. It takes the current detected bar code, assignes the values of
@@ -249,6 +225,7 @@ asynStatus NDPluginBar::push_corners(bar_QR_code &discovered, Image::SymbolItera
return asynSuccess;
}
+
/**
* Function that updates corner coordinate PVs to those of
* a specific detected bar code
@@ -279,6 +256,7 @@ asynStatus NDPluginBar::updateCorners(bar_QR_code &discovered, int imgHeight) {
return asynSuccess;
}
+
/**
* Function that uses zbar to scan image for barcodes
*
@@ -297,6 +275,7 @@ Image NDPluginBar::scan_image(Mat &img) {
return scannedImage;
}
+
/**
* Function that clears any non-overwritten barcode PVs between array callbacks
*
@@ -314,6 +293,7 @@ asynStatus NDPluginBar::clear_unused_barcode_pvs(int counter) {
return asynSuccess;
}
+
/**
* Function that does the barcode decoding. It is passed an image and a vector
* that will store all of the codes found in the image. A zbar scanner is initialized.
@@ -372,6 +352,7 @@ asynStatus NDPluginBar::decode_bar_codes(Mat &img) {
return asynSuccess;
}
+
/* Function that uses opencv methods with the locations of the discovered codes to place
* bounding boxes around the areas of the image that contain barcodes. This is
* so the user can confirm that the correct area of the image was discovered
@@ -385,7 +366,6 @@ asynStatus NDPluginBar::decode_bar_codes(Mat &img) {
asynStatus NDPluginBar::show_bar_codes(Mat &img) {
const char *functionName = "show_bar_codes";
try {
- cvtColor(img, img, COLOR_GRAY2RGB);
for (unsigned int i = 0; i < codes_in_image.size(); i++) {
vector barPoints = codes_in_image[i].position;
vector outside;
@@ -405,26 +385,21 @@ asynStatus NDPluginBar::show_bar_codes(Mat &img) {
}
}
-static void barcode_image_callback_wrapper(void* pPtr, NDArray* pArray){
- NDPluginBar* pPlugin = (NDPluginBar*) pPtr;
- pPlugin->barcode_image_callback(pArray);
-}
-asynStatus NDPluginBar::barcode_image_callback(NDArray* pArray){
- //start with an empty array for copy and array info
- NDArray *pScratch = NULL;
- Mat img;
+/**
+ * Function called on each image recieved from the camera that performs the actual barcode scanning and decoding.
+ * First, checks if code is inverted, and if so inverts it. Then, it calls the decode_bar_codes function
+ * which searches for barcodes in the image. If they were found without error, barcodes are then drawn onto the Mat.
+ * Then the mat is coinverted to the output image.
+ *
+ * @params[in]: img -> Mat converted from NDArray sent to plugin in process callbacks
+ * @params[out]: pArrayOut -> NDArray the plugin returns in endProcessCallbacks
+ * @return asynSuccess if processed correctly, asynError otherwise
+ */
+asynStatus NDPluginBar::barcode_image_callback(Mat &img, NDArray* pArrayOut){
const char* functionName = "barcode_image_callback";
- NDArrayInfo arrayInfo;
- // convert to Mat
- pArray->getInfo(&arrayInfo);
- asynStatus status = ndArray2Mat(pArray, &arrayInfo, img);
- if (status == asynError) {
- asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error converting to Mat\n", driverName, functionName);
- this->processing = false;
- return status;
- }
//check to see if we need to invert barcode
+ asynStatus status;
int inverted_code;
getIntegerParam(NDPluginBarInvertedBarcode, &inverted_code);
@@ -435,15 +410,16 @@ asynStatus NDPluginBar::barcode_image_callback(NDArray* pArray){
else {
status = decode_bar_codes(img);
}
+ cvtColor(img, img, COLOR_GRAY2RGB);
if (status != asynError) status = show_bar_codes(img);
- status = mat2NDArray(pScratch, img);
+ status = mat2NDArray(pArrayOut, img);
if (status == asynError) {
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error, image not processed correctly\n", driverName, functionName);
}
- this->processing = false;
return status;
}
+
/**
* Override of NDPluginDriver function. Used when selecting between barcodes
* for which corners should be shown.
@@ -483,6 +459,7 @@ asynStatus NDPluginBar::writeInt32(asynUser *pasynUser, epicsInt32 value) {
return status;
}
+
/* Process callbacks function inherited from NDPluginDriver.
* Here it is overridden, and the following steps are taken:
* 1) Check if the NDArray is mono, as zbar only accepts mono/grayscale images
@@ -496,65 +473,117 @@ asynStatus NDPluginBar::writeInt32(asynUser *pasynUser, epicsInt32 value) {
void NDPluginBar::processCallbacks(NDArray *pArray) {
static const char *functionName = "processCallbacks";
+ Mat img;
+ NDArrayInfo arrayInfo;
+ NDArray* pScratch;
+ NDDataType_t dataType = NDUInt8;
+ // output will always be in 3 channel RGB mode
+ NDColorMode_t colorMode = NDColorModeRGB1;
+ int ndims = 3;
+ size_t dims[ndims];
+
//call base class and get information about frame
NDPluginDriver::beginProcessCallbacks(pArray);
+ // convert to Mat
+ pArray->getInfo(&arrayInfo);
+ asynStatus status = ndArray2Mat(pArray, &arrayInfo, img);
+ if (status == asynError) {
+ asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error converting to Mat\n", driverName, functionName);
+ return;
+ }
+
+ // initialize output NDArray
+ Size matSize = img.size();
+ dims[0] = 3;
+ dims[1] = matSize.width;
+ dims[2] = matSize.height;
+
+ if (img.depth() == CV_8S)
+ dataType = NDInt8;
+ else if (img.depth() == CV_16U)
+ dataType = NDUInt16;
+ else if (img.depth() == CV_16S)
+ dataType = NDInt16;
+
+ pScratch = pNDArrayPool->alloc(ndims, dims, dataType, 0, NULL);
+ if (pScratch == NULL) {
+ asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error, unable to allocate array\n", driverName, functionName);
+ img.release();
+ return;
+ }
+
//unlock the mutex for the processing portion
this->unlock();
- if(!this->processing){
- asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s::%s Starting processing thread\n", driverName, functionName);
- this->processing = true;
- thread processing_thread(barcode_image_callback_wrapper, this, pArray);
- processing_thread.detach();
+ //if(!this->processing){
+ // asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s::%s Starting processing thread\n", driverName, functionName);
+ // this->processing = true;
+ // thread processing_thread(barcode_image_callback_wrapper, this, pArray);
+ // processing_thread.detach();
+ //}
+
+ // process the image
+ status = barcode_image_callback(img, pScratch);
+ if(status != asynSuccess){
+ pScratch->release();
+ img.release();
+ asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s Error processing image\n", driverName, functionName);
+ return;
}
this->lock();
+ // push the image out using endProcess callbacks
+ pScratch->uniqueId = pArray->uniqueId;
+ pScratch->pAttributeList->add("ColorMode", "Color Mode", NDAttrInt32, &colorMode);
+ endProcessCallbacks(pScratch, false, true);
+
callParamCallbacks();
}
+
//constructror from base class
NDPluginBar::NDPluginBar(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr,
int maxBuffers, size_t maxMemory,
- int priority, int stackSize)
+ int priority, int stackSize, int maxThreads)
/* Invoke the base class constructor */
: NDPluginDriver(portName, queueSize, blockingCallbacks,
NDArrayPort, NDArrayAddr, 1, maxBuffers, maxMemory,
asynInt32ArrayMask | asynFloat64ArrayMask | asynGenericPointerMask,
asynInt32ArrayMask | asynFloat64ArrayMask | asynGenericPointerMask,
- ASYN_MULTIDEVICE, 1, priority, stackSize, 1) {
+ 0, 1, priority, stackSize, maxThreads) {
char versionString[25];
//basic barcode parameters 1-5
- createParam(NDPluginBarBarcodeMessage1String, asynParamOctet, &NDPluginBarBarcodeMessage1);
- createParam(NDPluginBarBarcodeType1String, asynParamOctet, &NDPluginBarBarcodeType1);
- createParam(NDPluginBarBarcodeMessage2String, asynParamOctet, &NDPluginBarBarcodeMessage2);
- createParam(NDPluginBarBarcodeType2String, asynParamOctet, &NDPluginBarBarcodeType2);
- createParam(NDPluginBarBarcodeMessage3String, asynParamOctet, &NDPluginBarBarcodeMessage3);
- createParam(NDPluginBarBarcodeType3String, asynParamOctet, &NDPluginBarBarcodeType3);
- createParam(NDPluginBarBarcodeMessage4String, asynParamOctet, &NDPluginBarBarcodeMessage4);
- createParam(NDPluginBarBarcodeType4String, asynParamOctet, &NDPluginBarBarcodeType4);
- createParam(NDPluginBarBarcodeMessage5String, asynParamOctet, &NDPluginBarBarcodeMessage5);
- createParam(NDPluginBarBarcodeType5String, asynParamOctet, &NDPluginBarBarcodeType5);
+ createParam(NDPluginBarBarcodeMessage1String, asynParamOctet, &NDPluginBarBarcodeMessage1);
+ createParam(NDPluginBarBarcodeType1String, asynParamOctet, &NDPluginBarBarcodeType1);
+ createParam(NDPluginBarBarcodeMessage2String, asynParamOctet, &NDPluginBarBarcodeMessage2);
+ createParam(NDPluginBarBarcodeType2String, asynParamOctet, &NDPluginBarBarcodeType2);
+ createParam(NDPluginBarBarcodeMessage3String, asynParamOctet, &NDPluginBarBarcodeMessage3);
+ createParam(NDPluginBarBarcodeType3String, asynParamOctet, &NDPluginBarBarcodeType3);
+ createParam(NDPluginBarBarcodeMessage4String, asynParamOctet, &NDPluginBarBarcodeMessage4);
+ createParam(NDPluginBarBarcodeType4String, asynParamOctet, &NDPluginBarBarcodeType4);
+ createParam(NDPluginBarBarcodeMessage5String, asynParamOctet, &NDPluginBarBarcodeMessage5);
+ createParam(NDPluginBarBarcodeType5String, asynParamOctet, &NDPluginBarBarcodeType5);
//common params
- createParam(NDPluginBarNumberCodesString, asynParamInt32, &NDPluginBarNumberCodes);
- createParam(NDPluginBarCodeCornersString, asynParamInt32, &NDPluginBarCodeCorners);
- createParam(NDPluginBarInvertedBarcodeString, asynParamInt32, &NDPluginBarInvertedBarcode);
+ createParam(NDPluginBarNumberCodesString, asynParamInt32, &NDPluginBarNumberCodes);
+ createParam(NDPluginBarCodeCornersString, asynParamInt32, &NDPluginBarCodeCorners);
+ createParam(NDPluginBarInvertedBarcodeString, asynParamInt32, &NDPluginBarInvertedBarcode);
//x coordinates
- createParam(NDPluginBarUpperLeftXString, asynParamInt32, &NDPluginBarUpperLeftX);
- createParam(NDPluginBarUpperRightXString, asynParamInt32, &NDPluginBarUpperRightX);
- createParam(NDPluginBarLowerLeftXString, asynParamInt32, &NDPluginBarLowerLeftX);
- createParam(NDPluginBarLowerRightXString, asynParamInt32, &NDPluginBarLowerRightX);
+ createParam(NDPluginBarUpperLeftXString, asynParamInt32, &NDPluginBarUpperLeftX);
+ createParam(NDPluginBarUpperRightXString, asynParamInt32, &NDPluginBarUpperRightX);
+ createParam(NDPluginBarLowerLeftXString, asynParamInt32, &NDPluginBarLowerLeftX);
+ createParam(NDPluginBarLowerRightXString, asynParamInt32, &NDPluginBarLowerRightX);
//y coordinates
- createParam(NDPluginBarUpperLeftYString, asynParamInt32, &NDPluginBarUpperLeftY);
- createParam(NDPluginBarUpperRightYString, asynParamInt32, &NDPluginBarUpperRightY);
- createParam(NDPluginBarLowerLeftYString, asynParamInt32, &NDPluginBarLowerLeftY);
- createParam(NDPluginBarLowerRightYString, asynParamInt32, &NDPluginBarLowerRightY);
+ createParam(NDPluginBarUpperLeftYString, asynParamInt32, &NDPluginBarUpperLeftY);
+ createParam(NDPluginBarUpperRightYString, asynParamInt32, &NDPluginBarUpperRightY);
+ createParam(NDPluginBarLowerLeftYString, asynParamInt32, &NDPluginBarLowerLeftY);
+ createParam(NDPluginBarLowerRightYString, asynParamInt32, &NDPluginBarLowerRightY);
initPVArrays();
@@ -564,6 +593,7 @@ NDPluginBar::NDPluginBar(const char *portName, int queueSize, int blockingCallba
connectToArrayPort();
}
+
/**
* External configure function. This will be called from the IOC shell of the
* detector the plugin is attached to, and will create an instance of the plugin and start it
@@ -573,12 +603,13 @@ NDPluginBar::NDPluginBar(const char *portName, int queueSize, int blockingCallba
extern "C" int NDBarConfigure(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr,
int maxBuffers, size_t maxMemory,
- int priority, int stackSize) {
+ int priority, int stackSize, int maxThreads) {
NDPluginBar *pPlugin = new NDPluginBar(portName, queueSize, blockingCallbacks, NDArrayPort, NDArrayAddr,
- maxBuffers, maxMemory, priority, stackSize);
+ maxBuffers, maxMemory, priority, stackSize, maxThreads);
return pPlugin->start();
}
+
/* IOC shell arguments passed to the plugin configure function */
static const iocshArg initArg0 = {"portName", iocshArgString};
static const iocshArg initArg1 = {"frame queue size", iocshArgInt};
@@ -589,6 +620,7 @@ static const iocshArg initArg5 = {"maxBuffers", iocshArgInt};
static const iocshArg initArg6 = {"maxMemory", iocshArgInt};
static const iocshArg initArg7 = {"priority", iocshArgInt};
static const iocshArg initArg8 = {"stackSize", iocshArgInt};
+static const iocshArg initArg9 = {"maxThreads", iocshArgInt};
static const iocshArg *const initArgs[] = {&initArg0,
&initArg1,
&initArg2,
@@ -597,23 +629,28 @@ static const iocshArg *const initArgs[] = {&initArg0,
&initArg5,
&initArg6,
&initArg7,
- &initArg8};
+ &initArg8,
+ &initArg9};
+
/* Definition of the configure function for NDPluginBar in the IOC shell */
-static const iocshFuncDef initFuncDef = {"NDBarConfigure", 9, initArgs};
+static const iocshFuncDef initFuncDef = {"NDBarConfigure", 10, initArgs};
+
/* link the configure function with the passed args, and call it from the IOC shell */
static void initCallFunc(const iocshArgBuf *args) {
NDBarConfigure(args[0].sval, args[1].ival, args[2].ival,
args[3].sval, args[4].ival, args[5].ival,
- args[6].ival, args[7].ival, args[8].ival);
+ args[6].ival, args[7].ival, args[8].ival, args[9].ival);
}
+
/* function to register the configure function in the IOC shell */
extern "C" void NDBarRegister(void) {
iocshRegister(&initFuncDef, initCallFunc);
}
+
/* Exports plugin registration */
extern "C" {
epicsExportRegistrar(NDBarRegister);
diff --git a/barApp/barSrc/NDPluginBar.h b/barApp/barSrc/NDPluginBar.h
index 42a38a9..7ced12c 100755
--- a/barApp/barSrc/NDPluginBar.h
+++ b/barApp/barSrc/NDPluginBar.h
@@ -25,35 +25,36 @@ using namespace zbar;
#include "NDPluginDriver.h"
//version numbers
-#define BAR_VERSION 2
-#define BAR_REVISION 1
-#define BAR_MODIFICATION 0
+#define BAR_VERSION 2
+#define BAR_REVISION 2
+#define BAR_MODIFICATION 0
// Number of barcodes supported at one time
#define NUM_CODES 5
/* Here I will define all of the output data types once the database is written */
-#define NDPluginBarBarcodeMessage1String "BARCODE_MESSAGE1" //asynOctet
-#define NDPluginBarBarcodeType1String "BARCODE_TYPE1" //asynOctet
-#define NDPluginBarBarcodeMessage2String "BARCODE_MESSAGE2" //asynOctet
-#define NDPluginBarBarcodeType2String "BARCODE_TYPE2" //asynOctet
-#define NDPluginBarBarcodeMessage3String "BARCODE_MESSAGE3" //asynOctet
-#define NDPluginBarBarcodeType3String "BARCODE_TYPE3" //asynOctet
-#define NDPluginBarBarcodeMessage4String "BARCODE_MESSAGE4" //asynOctet
-#define NDPluginBarBarcodeType4String "BARCODE_TYPE4" //asynOctet
-#define NDPluginBarBarcodeMessage5String "BARCODE_MESSAGE5" //asynOctet
-#define NDPluginBarBarcodeType5String "BARCODE_TYPE5" //asynOctet
-#define NDPluginBarNumberCodesString "NUMBER_CODES" //asynInt32
-#define NDPluginBarCodeCornersString "CODE_CORNERS" //asynInt32
-#define NDPluginBarInvertedBarcodeString "INVERTED_CODE" //asynInt32
-#define NDPluginBarUpperLeftXString "UPPER_LEFT_X" //asynInt32
-#define NDPluginBarUpperRightXString "UPPER_RIGHT_X" //asynInt32
-#define NDPluginBarLowerLeftXString "LOWER_LEFT_X" //asynInt32
-#define NDPluginBarLowerRightXString "LOWER_RIGHT_X" //asynInt32
-#define NDPluginBarUpperLeftYString "UPPER_LEFT_Y" //asynInt32
-#define NDPluginBarUpperRightYString "UPPER_RIGHT_Y" //asynInt32
-#define NDPluginBarLowerLeftYString "LOWER_LEFT_Y" //asynInt32
-#define NDPluginBarLowerRightYString "LOWER_RIGHT_Y" //asynInt32
+#define NDPluginBarBarcodeMessage1String "BARCODE_MESSAGE1" //asynOctet
+#define NDPluginBarBarcodeType1String "BARCODE_TYPE1" //asynOctet
+#define NDPluginBarBarcodeMessage2String "BARCODE_MESSAGE2" //asynOctet
+#define NDPluginBarBarcodeType2String "BARCODE_TYPE2" //asynOctet
+#define NDPluginBarBarcodeMessage3String "BARCODE_MESSAGE3" //asynOctet
+#define NDPluginBarBarcodeType3String "BARCODE_TYPE3" //asynOctet
+#define NDPluginBarBarcodeMessage4String "BARCODE_MESSAGE4" //asynOctet
+#define NDPluginBarBarcodeType4String "BARCODE_TYPE4" //asynOctet
+#define NDPluginBarBarcodeMessage5String "BARCODE_MESSAGE5" //asynOctet
+#define NDPluginBarBarcodeType5String "BARCODE_TYPE5" //asynOctet
+#define NDPluginBarNumberCodesString "NUMBER_CODES" //asynInt32
+#define NDPluginBarCodeCornersString "CODE_CORNERS" //asynInt32
+#define NDPluginBarInvertedBarcodeString "INVERTED_CODE" //asynInt32
+#define NDPluginBarUpperLeftXString "UPPER_LEFT_X" //asynInt32
+#define NDPluginBarUpperRightXString "UPPER_RIGHT_X" //asynInt32
+#define NDPluginBarLowerLeftXString "LOWER_LEFT_X" //asynInt32
+#define NDPluginBarLowerRightXString "LOWER_RIGHT_X" //asynInt32
+#define NDPluginBarUpperLeftYString "UPPER_LEFT_Y" //asynInt32
+#define NDPluginBarUpperRightYString "UPPER_RIGHT_Y" //asynInt32
+#define NDPluginBarLowerLeftYString "LOWER_LEFT_Y" //asynInt32
+#define NDPluginBarLowerRightYString "LOWER_RIGHT_Y" //asynInt32
+
/* structure that contains information about the bar/QR code */
typedef struct {
@@ -64,109 +65,110 @@ typedef struct {
/* class that does barcode readings */
class NDPluginBar : public NDPluginDriver {
- public:
- NDPluginBar(const char *portName, int queueSize, int blockingCallbacks,
- const char *NDArrayPort, int NDArrayAddr, int maxBuffers,
- size_t maxMemory, int priority, int stackSize);
+ public:
+ NDPluginBar(const char *portName, int queueSize, int blockingCallbacks,
+ const char *NDArrayPort, int NDArrayAddr, int maxBuffers,
+ size_t maxMemory, int priority, int stackSize, int maxThreads);
+
+ //~NDPluginBar();
- //~NDPluginBar();
+ void processCallbacks(NDArray *pArray);
+ asynStatus barcode_image_callback(Mat &img, NDArray* pArrayOut);
+ virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
- void processCallbacks(NDArray *pArray);
- asynStatus barcode_image_callback(NDArray* pArray);
- virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
+ protected:
+ //in this section i define the coords of database vals
- protected:
- //in this section i define the coords of database vals
+ //message contained in bar code and its type
+ int NDPluginBarBarcodeMessage1;
+ #define ND_BAR_FIRST_PARAM NDPluginBarBarcodeMessage1
+ int NDPluginBarBarcodeType1;
- //message contained in bar code and its type
- int NDPluginBarBarcodeMessage1;
-#define ND_BAR_FIRST_PARAM NDPluginBarBarcodeMessage1
- int NDPluginBarBarcodeType1;
+ int NDPluginBarBarcodeMessage2;
+ int NDPluginBarBarcodeType2;
- int NDPluginBarBarcodeMessage2;
- int NDPluginBarBarcodeType2;
+ int NDPluginBarBarcodeMessage3;
+ int NDPluginBarBarcodeType3;
- int NDPluginBarBarcodeMessage3;
- int NDPluginBarBarcodeType3;
+ int NDPluginBarBarcodeMessage4;
+ int NDPluginBarBarcodeType4;
- int NDPluginBarBarcodeMessage4;
- int NDPluginBarBarcodeType4;
+ int NDPluginBarBarcodeMessage5;
+ int NDPluginBarBarcodeType5;
- int NDPluginBarBarcodeMessage5;
- int NDPluginBarBarcodeType5;
+ //number of codes found
+ int NDPluginBarNumberCodes;
- //number of codes found
- int NDPluginBarNumberCodes;
+ int NDPluginBarCodeCorners;
- int NDPluginBarCodeCorners;
+ //white on black/ black on white
+ int NDPluginBarInvertedBarcode;
- //white on black/ black on white
- int NDPluginBarInvertedBarcode;
+ //upper left pixel of found bar code
+ int NDPluginBarUpperLeftX;
- //upper left pixel of found bar code
- int NDPluginBarUpperLeftX;
+ //upper right pixel of found bar code
+ int NDPluginBarUpperRightX;
- //upper right pixel of found bar code
- int NDPluginBarUpperRightX;
+ //lower left pixel of found bar code
+ int NDPluginBarLowerLeftX;
- //lower left pixel of found bar code
- int NDPluginBarLowerLeftX;
+ //lower right pixel of found bar code
+ int NDPluginBarLowerRightX;
- //lower right pixel of found bar code
- int NDPluginBarLowerRightX;
+ //upper left pixel of found bar code
+ int NDPluginBarUpperLeftY;
- //upper left pixel of found bar code
- int NDPluginBarUpperLeftY;
+ //upper right pixel of found bar code
+ int NDPluginBarUpperRightY;
- //upper right pixel of found bar code
- int NDPluginBarUpperRightY;
+ //lower left pixel of found bar code
+ int NDPluginBarLowerLeftY;
- //lower left pixel of found bar code
- int NDPluginBarLowerLeftY;
+ //lower right pixel of found bar code
+ int NDPluginBarLowerRightY;
- //lower right pixel of found bar code
- int NDPluginBarLowerRightY;
-#define ND_BAR_LAST_PARAM NDPluginBarLowerRightY
+ #define ND_BAR_LAST_PARAM NDPluginBarLowerRightY
- private:
- // processing thread
- bool processing = false;
+ private:
+ // processing thread - unused
+ //bool processing = false;
- // arrays that hold indexes of PVs for messages and types
- int barcodeMessagePVs[NUM_CODES];
- int barcodeTypePVs[NUM_CODES];
+ // arrays that hold indexes of PVs for messages and types
+ int barcodeMessagePVs[NUM_CODES];
+ int barcodeTypePVs[NUM_CODES];
- // arrays that hold indexes for PVs for corners
- int cornerXPVs[4];
- int cornerYPVs[4];
+ // arrays that hold indexes for PVs for corners
+ int cornerXPVs[4];
+ int cornerYPVs[4];
- // vector that stores currently discovered barcodes
- vector codes_in_image;
- asynStatus clearPreviousCodes();
- asynStatus clear_unused_barcode_pvs(int counter);
+ // vector that stores currently discovered barcodes
+ vector codes_in_image;
+ asynStatus clearPreviousCodes();
+ asynStatus clear_unused_barcode_pvs(int counter);
- // functions called on plugin initialization
- asynStatus initPVArrays();
+ // functions called on plugin initialization
+ asynStatus initPVArrays();
- // image type conversion functions
- void printCVError(cv::Exception &e, const char *functionName);
- asynStatus ndArray2Mat(NDArray *pArray, NDArrayInfo *arrayInfo, Mat &img);
- asynStatus mat2NDArray(NDArray *pScratch, Mat &img);
+ // image type conversion functions
+ void printCVError(cv::Exception &e, const char *functionName);
+ asynStatus ndArray2Mat(NDArray *pArray, NDArrayInfo *arrayInfo, Mat &img);
+ asynStatus mat2NDArray(NDArray *pScratch, Mat &img);
- // Decoding functions
- Image scan_image(Mat &img);
- asynStatus decode_bar_codes(Mat &img);
+ // Decoding functions
+ Image scan_image(Mat &img);
+ asynStatus decode_bar_codes(Mat &img);
- //function that displays detected bar codes
- asynStatus show_bar_codes(Mat &img);
+ //function that displays detected bar codes
+ asynStatus show_bar_codes(Mat &img);
- //function that allows for reading inverted barcodes
- asynStatus fix_inverted(Mat &img);
+ //function that allows for reading inverted barcodes
+ asynStatus fix_inverted(Mat &img);
- //function that pushes barcode coordinate data to PVs
- asynStatus push_corners(bar_QR_code &discovered, Image::SymbolIterator &symbol, int update_corners, int imgHeight);
- asynStatus updateCorners(bar_QR_code &discovered, int imgHeight);
+ //function that pushes barcode coordinate data to PVs
+ asynStatus push_corners(bar_QR_code &discovered, Image::SymbolIterator &symbol, int update_corners, int imgHeight);
+ asynStatus updateCorners(bar_QR_code &discovered, int imgHeight);
};
#define NUM_BAR_PARAMS ((int)(&ND_BAR_LAST_PARAM - &ND_BAR_FIRST_PARAM + 1))
diff --git a/docs/ADPluginBar/ADPluginBar.rst b/docs/ADPluginBar/ADPluginBar.rst
index d018256..33e8794 100644
--- a/docs/ADPluginBar/ADPluginBar.rst
+++ b/docs/ADPluginBar/ADPluginBar.rst
@@ -99,9 +99,25 @@ prosilica camera*
Release Notes
-------------
-R2-1 (8-May-2019)
+R2-2 (5-July-2019)
+~~~~~~~~~~~~~~~~~~
---------------
+- Features Added:
+
+ - Support for maxThreads as used with other ADPlugins
+
+- Bug Fixes/Improvements
+
+ - Removed addAttribute call for data type
+ - Edit to use endProcessCallbacks instead of doCallbacksGenericPointer
+ - Doc/comments edited
+
+- Possible future plans
+
+ - PV for toggling image callbacks - Performance improvement and image view not always needed.
+
+R2-1 (8-May-2019)
+~~~~~~~~~~~~~~~~~
- Features Added:
diff --git a/docs/index.html b/docs/index.html
index 6c04a71..32113a3 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -54,8 +54,24 @@ Using ADPluginBar
Release Notes
-R2-1 (8-May-2019)
-
+R2-2 (5-July-2019)
+
+- Features Added:
+- Support for maxThreads as used with other ADPlugins
+
+
+- Bug Fixes/Improvements
+- Removed addAttribute call for data type
+- Edit to use endProcessCallbacks instead of doCallbacksGenericPointer
+- Doc/comments edited
+
+
+- Possible future plans
+- PV for toggling image callbacks - Performance improvement and image view not always needed.
+
+
+
+R2-1 (8-May-2019)
- Features Added:
- Threading has been added (similar to NDPluginDmtx) for much faster performance, and no lost frames