diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f828d65..1c8f850c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,6 +149,12 @@ if(PLUGIN_DummyGrabber) add_subdirectory(DummyGrabber) endif(PLUGIN_DummyGrabber) +# DummyMultiChannelGrabber +option(PLUGIN_DummyMultiChannelGrabber "Build with this plugin." ON) +if(PLUGIN_DummyMultiChannelGrabber) + add_subdirectory(DummyMultiChannelGrabber) +endif(PLUGIN_DummyMultiChannelGrabber) + # DummyMotor option(PLUGIN_DummyMotor "Build with this plugin." ON) if(PLUGIN_DummyMotor) diff --git a/DummyGrabber/DummyGrabber.cpp b/DummyGrabber/DummyGrabber.cpp index 7566305a..2932b930 100644 --- a/DummyGrabber/DummyGrabber.cpp +++ b/DummyGrabber/DummyGrabber.cpp @@ -25,26 +25,16 @@ #include "DummyGrabber.h" -#define _USE_MATH_DEFINES // needs to be defined to enable standard declartions of PI constant -#include "math.h" - #ifndef WIN32 - #include +#include #endif -#include -#include -#include -#include - -#include -#include -#include + #include "dockWidgetDummyGrabber.h" -#include "pluginVersion.h" -#include "gitVersion.h" #include "common/helperCommon.h" #include "common/paramMeta.h" +#include "gitVersion.h" +#include "pluginVersion.h" #ifdef WIN32 #include @@ -52,22 +42,23 @@ //---------------------------------------------------------------------------------------------------------------------------------- /** @func fastrand -* @brief function for pseudo random values -* -* This function delivers the noise for the image. -*/ -template inline _Tp fastrand(cv::RNG &rng, _Tp maxval, float offset, float gain) + * @brief function for pseudo random values + * + * This function delivers the noise for the image. + */ +template inline _Tp fastrand(cv::RNG& rng, _Tp maxval, float offset, float gain) { return cv::saturate_cast<_Tp>(offset * maxval + gain * (((ito::uint32)rng.next()) & maxval)); } //---------------------------------------------------------------------------------------------------------------------------------- /** @func fastrand -* @brief function for pseudo random values -* -* This function delivers the noise for the image. -*/ -template inline _Tp fastrand_mean(cv::RNG &rng, _Tp maxval, ito::uint8 numMeans, float offset, float gain) + * @brief function for pseudo random values + * + * This function delivers the noise for the image. + */ +template +inline _Tp fastrand_mean(cv::RNG& rng, _Tp maxval, ito::uint8 numMeans, float offset, float gain) { ito::uint32 val = 0; @@ -81,11 +72,11 @@ template inline _Tp fastrand_mean(cv::RNG &rng, _Tp maxval, ito::u //---------------------------------------------------------------------------------------------------------------------------------- /** @func gaussFunc -* @brief function for 2d Gaussian function -* -* This function delivers a 2d dataObject with a Gaussian function -*/ -template ito::RetVal gaussFunc(cv::RNG &rng, ito::DataObject dObj, float amplitude) + * @brief function for 2d Gaussian function + * + * This function delivers a 2d dataObject with a Gaussian function + */ +template ito::RetVal gaussFunc(cv::RNG& rng, ito::DataObject dObj, float amplitude) { int width = dObj.getSize(1); int height = dObj.getSize(0); @@ -103,11 +94,13 @@ template ito::RetVal gaussFunc(cv::RNG &rng, ito::DataObject dObj, for (int y = 0; y < height; y++) { rowPtr = dObj.rowPtr<_Tp>(planeID, y); - yval = ((y - height / 2 + yRandOffset) * ((float)y - height / 2 + yRandOffset)) / (2.0f * sigmaY * sigmaY); + yval = ((y - height / 2 + yRandOffset) * ((float)y - height / 2 + yRandOffset)) / + (2.0f * sigmaY * sigmaY); for (int x = 0; x < width; x++) { - xval = ((x - width / 2 + xRandOffset) * ((float)x - width / 2 + xRandOffset)) / (2.0f * sigmaX * sigmaX); + xval = ((x - width / 2 + xRandOffset) * ((float)x - width / 2 + xRandOffset)) / + (2.0f * sigmaX * sigmaX); rowPtr[x] = (float)(amplitude - aRandOfset) * exp(-(xval + yval)); } } @@ -118,18 +111,17 @@ template ito::RetVal gaussFunc(cv::RNG &rng, ito::DataObject dObj, //---------------------------------------------------------------------------------------------------------------------------------- /*! \class DummyGrabberInterface - \brief Small interface class for class DummyGrabber. This class contains basic information about DummyGrabber as is able to - create one or more new instances of DummyGrabber. + \brief Small interface class for class DummyGrabber. This class contains basic information about + DummyGrabber as is able to create one or more new instances of DummyGrabber. */ //---------------------------------------------------------------------------------------------------------------------------------- //! creates new instance of DummyGrabber and returns the instance-pointer. /*! - \param [in,out] addInInst is a double pointer of type ito::AddInBase. The newly created DummyGrabber-instance is stored in *addInInst - \return retOk - \sa DummyGrabber + \param [in,out] addInInst is a double pointer of type ito::AddInBase. The newly created + DummyGrabber-instance is stored in *addInInst \return retOk \sa DummyGrabber */ -ito::RetVal DummyGrabberInterface::getAddInInst(ito::AddInBase **addInInst) +ito::RetVal DummyGrabberInterface::getAddInInst(ito::AddInBase** addInInst) { NEW_PLUGININSTANCE(DummyGrabber) return ito::retOk; @@ -142,7 +134,7 @@ ito::RetVal DummyGrabberInterface::getAddInInst(ito::AddInBase **addInInst) \return retOk \sa DummyGrabber */ -ito::RetVal DummyGrabberInterface::closeThisInst(ito::AddInBase **addInInst) +ito::RetVal DummyGrabberInterface::closeThisInst(ito::AddInBase** addInInst) { REMOVE_PLUGININSTANCE(DummyGrabber) return ito::retOk; @@ -151,9 +143,10 @@ ito::RetVal DummyGrabberInterface::closeThisInst(ito::AddInBase **addInInst) //---------------------------------------------------------------------------------------------------------------------------------- //! constructor for interace /*! - defines the plugin type (dataIO and grabber) and sets the plugins object name. If the real plugin (here: DummyGrabber) should or must - be initialized (e.g. by a Python call) with mandatory or optional parameters, please initialize both vectors m_initParamsMand - and m_initParamsOpt within this constructor. + defines the plugin type (dataIO and grabber) and sets the plugins object name. If the real + plugin (here: DummyGrabber) should or must be initialized (e.g. by a Python call) with mandatory + or optional parameters, please initialize both vectors m_initParamsMand and m_initParamsOpt + within this constructor. */ DummyGrabberInterface::DummyGrabberInterface() { @@ -163,25 +156,29 @@ DummyGrabberInterface::DummyGrabberInterface() m_type = ito::typeDataIO | ito::typeGrabber; setObjectName("DummyGrabber"); - //for the docstring, please don't set any spaces at the beginning of the line. -/* char docstring[] = \ -"The DummyGrabber is a virtual camera which emulates a camera with white noise. \n\ -\n\ -The camera is initialized with a maximum width and height of the simulated camera chip (both need to be a multiple of 4). \ -The noise is always scaled in the range between 0 and the current bitdepth (bpp - bit per pixel). The real size of the camera \ -image is controlled using the parameter 'roi' if the sizes stay within the limits given by the size of the camera chip.\n\ -\n\ -You can initialize this camera either as a 2D sensor with a width and height >= 4 or as line camera whose height is equal to 1. \n\ -\n\ -This plugin can also be used as template for other grabber.";*/ - - m_description = QObject::tr("A virtual white noise grabber"); -// m_detaildescription = QObject::tr(docstring); + // for the docstring, please don't set any spaces at the beginning of the line. + /* char docstring[] = \ + "The DummyGrabber is a virtual camera which emulates a camera with white noise. \n\ + \n\ + The camera is initialized with a maximum width and height of the simulated camera chip (both + need to be a multiple of 4). \ + The noise is always scaled in the range between 0 and the current bitdepth (bpp - bit per + pixel). The real size of the camera \ + image is controlled using the parameter 'roi' if the sizes stay within the limits given by the + size of the camera chip.\n\ + \n\ + You can initialize this camera either as a 2D sensor with a width and height >= 4 or as line + camera whose height is equal to 1. \n\ + \n\ + This plugin can also be used as template for other grabber.";*/ + + m_description = QObject::tr("A virtual grabber with white noise or a Gaussian spot."); + // m_detaildescription = QObject::tr(docstring); m_detaildescription = QObject::tr( -"The DummyGrabber is a virtual camera which emulates a camera with white noise. \n\ + "The DummyGrabber is a virtual camera which emulates a camera with white noise or a Gaussian spot like a laser beam. \n\ \n\ The camera is initialized with a maximum width and height of the simulated camera chip (both need to be a multiple of 4). \ -You can choose between different image types (noise, GaussianSpot). \ +You can choose between different image types (noise, GaussianSpot, GaussianSpotArray). \ The value range is always scaled in the range between 0 and the current bitdepth (bpp - bit per pixel). \ The gaussianSpot has some random noise for the position and amplitude to move around a bit. The real size of the camera \ image is controlled using the parameter 'roi' if the sizes stay within the limits given by the size of the camera chip.\n\ @@ -190,25 +187,49 @@ You can initialize this camera either as a 2D sensor with a width and height >= \n\ This plugin can also be used as template for other grabber."); - m_author = "C. Kohler, W. Lyda, ITO, University Stuttgart"; + m_author = "C. Kohler, W. Lyda, J. Krauter; ITO, University Stuttgart"; m_version = (PLUGIN_VERSION_MAJOR << 16) + (PLUGIN_VERSION_MINOR << 8) + PLUGIN_VERSION_PATCH; - m_minItomVer = CREATEVERSION(1,4,0); + m_minItomVer = CREATEVERSION(1, 4, 0); m_maxItomVer = MAXVERSION; m_license = QObject::tr("Licensed under LPGL."); m_aboutThis = tr(GITVERSION); m_initParamsMand.clear(); - ito::Param param("maxXSize", ito::ParamBase::Int, 640, new ito::IntMeta(4, 4096, 4), tr("Width of virtual sensor chip").toLatin1().data()); + ito::Param param( + "maxXSize", + ito::ParamBase::Int, + 640, + new ito::IntMeta(4, 4096, 4), + tr("Width of virtual sensor chip").toLatin1().data()); m_initParamsOpt.append(param); - param = ito::Param("maxYSize", ito::ParamBase::Int, 480, new ito::IntMeta(1, 4096, 1), tr("Height of virtual sensor chip, please set this value to 1 (line camera) or a value dividable by 4 for a 2D camera.").toLatin1().data()); + param = ito::Param( + "maxYSize", + ito::ParamBase::Int, + 480, + new ito::IntMeta(1, 4096, 1), + tr("Height of virtual sensor chip, please set this value to 1 (line camera) or a value " + "dividable by 4 for a 2D camera.") + .toLatin1() + .data()); m_initParamsOpt.append(param); - param = ito::Param("bpp", ito::ParamBase::Int, 8, new ito::IntMeta(8, 30, 2), tr("Bits per Pixel, usually 8-16bit grayvalues").toLatin1().data()); + param = ito::Param( + "bpp", + ito::ParamBase::Int, + 8, + new ito::IntMeta(8, 30, 2), + tr("Bits per Pixel, usually 8-16bit grayvalues").toLatin1().data()); m_initParamsOpt.append(param); - param = ito::Param("imageType", ito::ParamBase::String | ito::ParamBase::In, "noise", tr("Available dummy image types: noise (default), gaussianSpot").toLatin1().data()); + param = ito::Param( + "imageType", + ito::ParamBase::String | ito::ParamBase::In, + "noise", + tr("Available dummy image types: noise (default), gaussianSpot, gaussianSpotArray") + .toLatin1() + .data()); ito::StringMeta sm(ito::StringMeta::String, "noise"); sm.addItem("gaussianSpot"); sm.addItem("gaussianSpotArray"); @@ -228,24 +249,28 @@ DummyGrabberInterface::~DummyGrabberInterface() } //---------------------------------------------------------------------------------------------------------------------------------- -// this makro registers the class DummyGrabberInterface with the name DummyGrabberinterface as plugin for the Qt-System (see Qt-DOC) +// this makro registers the class DummyGrabberInterface with the name DummyGrabberinterface as +// plugin for the Qt-System (see Qt-DOC) //---------------------------------------------------------------------------------------------------------------------------------- /*! \class DummyGrabber - \brief Class for the DummyGrabber. The DummyGrabber is able to create noisy images or simulate a typical WLI or confocal image signal. + \brief Class for the DummyGrabber. The DummyGrabber is able to create noisy images or simulate a + typical WLI or confocal image signal. - Usually every method in this class can be executed in an own thread. Only the constructor, destructor, showConfDialog will be executed by the - main (GUI) thread. + Usually every method in this class can be executed in an own thread. Only the constructor, + destructor, showConfDialog will be executed by the main (GUI) thread. */ //---------------------------------------------------------------------------------------------------------------------------------- -//! shows the configuration dialog. This method must be executed in the main (GUI) thread and is usually called by the addIn-Manager. +//! shows the configuration dialog. This method must be executed in the main (GUI) thread and is +//! usually called by the addIn-Manager. /*! - creates new instance of dialogDummyGrabber, calls the method setVals of dialogDummyGrabber, starts the execution loop and if the dialog - is closed, reads the new parameter set and deletes the dialog. + creates new instance of dialogDummyGrabber, calls the method setVals of dialogDummyGrabber, + starts the execution loop and if the dialog is closed, reads the new parameter set and deletes + the dialog. \return retOk \sa dialogDummyGrabber @@ -258,88 +283,159 @@ const ito::RetVal DummyGrabber::showConfDialog(void) //---------------------------------------------------------------------------------------------------------------------------------- //! constructor for DummyGrabber /*! - In this constructor the m_params-vector with all parameters, which are accessible by getParam or setParam, is built. - Additionally the optional docking widget for the DummyGrabber's toolbar is instantiated and created by createDockWidget. + In this constructor the m_params-vector with all parameters, which are accessible by getParam or + setParam, is built. Additionally the optional docking widget for the DummyGrabber's toolbar is + instantiated and created by createDockWidget. \param [in] uniqueID is an unique identifier for this DummyGrabber-instance \sa ito::tParam, createDockWidget, setParam, getParam */ DummyGrabber::DummyGrabber() : - AddInGrabber(), - m_isgrabbing(false), - m_totalBinning(1), - m_lineCamera(false), + AddInGrabber(), m_isgrabbing(false), m_totalBinning(1), m_lineCamera(false), + m_startOfLastAcquisition(0), m_imageType(imgTypeNoise) { - ito::DoubleMeta *dm; + ito::DoubleMeta* dm; - ito::Param paramVal("name", ito::ParamBase::String | ito::ParamBase::Readonly, "DummyGrabber", "GrabberName"); + ito::Param paramVal( + "name", ito::ParamBase::String | ito::ParamBase::Readonly, "DummyGrabber", "GrabberName"); paramVal.setMeta(new ito::StringMeta(ito::StringMeta::String, "General"), true); m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("frame_time", ito::ParamBase::Double, 0.0, 60.0, 0.0, tr("Minimum time between the start of two consecutive acquisitions [s], default: 0.0.").toLatin1().data()); + paramVal = ito::Param( + "frame_time", + ito::ParamBase::Double, + 0.0, + 60.0, + 0.0, + tr("Minimum time between the start of two consecutive acquisitions [s], default: 0.0.") + .toLatin1() + .data()); dm = paramVal.getMetaT(); dm->setCategory("AcquisitionControl"); dm->setUnit("s"); - dm->setRepresentation(ito::ParamMeta::Linear); //show a linear slider in generic paramEditorWidget... + dm->setRepresentation( + ito::ParamMeta::Linear); // show a linear slider in generic paramEditorWidget... m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("integration_time", ito::ParamBase::Double, 0.0, 60.0, 0.0, tr("Minimum integration time for an acquisition [s], default: 0.0 (as fast as possible).").toLatin1().data()); + paramVal = ito::Param( + "integration_time", + ito::ParamBase::Double, + 0.0, + 60.0, + 0.0, + tr("Minimum integration time for an acquisition [s], default: 0.0 (as fast as possible).") + .toLatin1() + .data()); dm = paramVal.getMetaT(); dm->setCategory("AcquisitionControl"); dm->setUnit("s"); - dm->setRepresentation(ito::ParamMeta::Linear); //show a linear slider in generic paramEditorWidget... + dm->setRepresentation( + ito::ParamMeta::Linear); // show a linear slider in generic paramEditorWidget... m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("gain", ito::ParamBase::Double, 0.0, 1.0, 1.0, tr("Virtual gain").toLatin1().data()); + paramVal = ito::Param( + "gain", ito::ParamBase::Double, 0.0, 1.0, 1.0, tr("Virtual gain").toLatin1().data()); dm = paramVal.getMetaT(); dm->setCategory("AcquisitionControl"); - dm->setRepresentation(ito::ParamMeta::Linear); //show a linear slider in generic paramEditorWidget... + dm->setRepresentation( + ito::ParamMeta::Linear); // show a linear slider in generic paramEditorWidget... m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("offset", ito::ParamBase::Double, 0.0, 1.0, 0.0, tr("Virtual offset").toLatin1().data()); + paramVal = ito::Param( + "offset", ito::ParamBase::Double, 0.0, 1.0, 0.0, tr("Virtual offset").toLatin1().data()); dm = paramVal.getMetaT(); dm->setCategory("AcquisitionControl"); - dm->setRepresentation(ito::ParamMeta::Linear); //show a linear slider in generic paramEditorWidget... + dm->setRepresentation( + ito::ParamMeta::Linear); // show a linear slider in generic paramEditorWidget... m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("binning", ito::ParamBase::Int, 101, 404, 101, tr("Binning of different pixel, binning = x-factor * 100 + y-factor").toLatin1().data()); + paramVal = ito::Param( + "binning", + ito::ParamBase::Int, + 101, + 404, + 101, + tr("Binning of different pixel, binning = x-factor * 100 + y-factor").toLatin1().data()); paramVal.getMetaT()->setCategory("ImageFormatControl"); m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("sizex", ito::ParamBase::Int | ito::ParamBase::Readonly, 4, 4096, 4096, tr("size in x (cols) [px]").toLatin1().data()); + paramVal = ito::Param( + "sizex", + ito::ParamBase::Int | ito::ParamBase::Readonly, + 4, + 4096, + 4096, + tr("size in x (cols) [px]").toLatin1().data()); paramVal.getMetaT()->setCategory("ImageFormatControl"); m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("sizey", ito::ParamBase::Int | ito::ParamBase::Readonly, 1, 4096, 4096, tr("size in y (rows) [px]").toLatin1().data()); + paramVal = ito::Param( + "sizey", + ito::ParamBase::Int | ito::ParamBase::Readonly, + 1, + 4096, + 4096, + tr("size in y (rows) [px]").toLatin1().data()); paramVal.getMetaT()->setCategory("ImageFormatControl"); m_params.insert(paramVal.getName(), paramVal); int roi[] = {0, 0, 2048, 2048}; - paramVal = ito::Param("roi", ito::ParamBase::IntArray, 4, roi, tr("ROI (x,y,width,height) [this replaces the values x0,x1,y0,y1]").toLatin1().data()); - ito::RectMeta *rm = new ito::RectMeta(ito::RangeMeta(roi[0], roi[0] + roi[2] - 1), ito::RangeMeta(roi[1], roi[1] + roi[3] - 1), "ImageFormatControl"); + paramVal = ito::Param( + "roi", + ito::ParamBase::IntArray, + 4, + roi, + tr("ROI (x,y,width,height) [this replaces the values x0,x1,y0,y1]").toLatin1().data()); + ito::RectMeta* rm = new ito::RectMeta( + ito::RangeMeta(roi[0], roi[0] + roi[2] - 1), + ito::RangeMeta(roi[1], roi[1] + roi[3] - 1), + "ImageFormatControl"); paramVal.setMeta(rm, true); m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("bpp", ito::ParamBase::Int, 8, new ito::IntMeta(8, 30, 2, "ImageFormatControl"), tr("bitdepth of images").toLatin1().data()); + paramVal = ito::Param( + "bpp", + ito::ParamBase::Int, + 8, + new ito::IntMeta(8, 30, 2, "ImageFormatControl"), + tr("bitdepth of images").toLatin1().data()); m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("demoRegexpString", ito::ParamBase::String, "", tr("matches strings without whitespaces").toLatin1().data()); - paramVal.setMeta(new ito::StringMeta(ito::StringMeta::RegExp, "^\\S+$", "DemoParameters"), true); + paramVal = ito::Param( + "demoRegexpString", + ito::ParamBase::String, + "", + tr("matches strings without whitespaces").toLatin1().data()); + paramVal.setMeta( + new ito::StringMeta(ito::StringMeta::RegExp, "^\\S+$", "DemoParameters"), true); m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("demoWildcardString", ito::ParamBase::String, "test.bmp", tr("dummy filename of a bmp file, pattern: *.bmp").toLatin1().data()); - paramVal.setMeta(new ito::StringMeta(ito::StringMeta::Wildcard, "*.bmp", "DemoParameters"), true); + paramVal = ito::Param( + "demoWildcardString", + ito::ParamBase::String, + "test.bmp", + tr("dummy filename of a bmp file, pattern: *.bmp").toLatin1().data()); + paramVal.setMeta( + new ito::StringMeta(ito::StringMeta::Wildcard, "*.bmp", "DemoParameters"), true); m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("demoEnumString", ito::ParamBase::String, "mode 1", tr("enumeration string (mode 1, mode 2, mode 3)").toLatin1().data()); - ito::StringMeta *sm = new ito::StringMeta(ito::StringMeta::String, "mode 1", "DemoParameters"); + paramVal = ito::Param( + "demoEnumString", + ito::ParamBase::String, + "mode 1", + tr("enumeration string (mode 1, mode 2, mode 3)").toLatin1().data()); + ito::StringMeta* sm = new ito::StringMeta(ito::StringMeta::String, "mode 1", "DemoParameters"); sm->addItem("mode 2"); sm->addItem("mode 3"); paramVal.setMeta(sm, true); m_params.insert(paramVal.getName(), paramVal); - paramVal = ito::Param("demoArbitraryString", ito::ParamBase::String, "any string", tr("any string allowed").toLatin1().data()); + paramVal = ito::Param( + "demoArbitraryString", + ito::ParamBase::String, + "any string", + tr("any string allowed").toLatin1().data()); sm = new ito::StringMeta(ito::StringMeta::String); sm->setCategory("DemoParameters"); paramVal.setMeta(sm, true); @@ -362,14 +458,64 @@ DummyGrabber::DummyGrabber() : paramVal.setMeta(sm, true); m_params.insert(paramVal.getName(), paramVal); + ito::float64 offset[2] = {0.0, 0.0}; + paramVal = ito::Param( + "axisOffset", + ito::ParamBase::DoubleArray, + 2, + offset, + new ito::DoubleArrayMeta( + -std::numeric_limits::max(), std::numeric_limits::max(), 0.0, 2, 2), + tr("axis offset").toLatin1().data()); + m_params.insert(paramVal.getName(), paramVal); + + ito::float64 scale[2] = {1.0e-3, 1.0e-3}; + paramVal = ito::Param( + "axisScale", + ito::ParamBase::DoubleArray, + 2, + scale, + new ito::DoubleArrayMeta( + -std::numeric_limits::max(), std::numeric_limits::max(), 0, 2, 2), + tr("axis scale").toLatin1().data()); + m_params.insert(paramVal.getName(), paramVal); + + paramVal = ito::Param("axisUnit", ito::ParamBase::StringList, nullptr, "axis unit"); + ito::ByteArray axisUnit[] = {ito::ByteArray("mm"), ito::ByteArray("mm")}; + paramVal.setVal(axisUnit, 2); + m_params.insert(paramVal.getName(), paramVal); + + paramVal = ito::Param( + "axisDescription", + ito::ParamBase::StringList, + nullptr, + "axis description"); + ito::ByteArray axisDescription[] = {ito::ByteArray("y axis"), ito::ByteArray("x axis")}; + paramVal.setVal(axisDescription, 2); + m_params.insert(paramVal.getName(), paramVal); + + paramVal = ito::Param( + "valueDescription", + ito::ParamBase::String, + "counts", + tr("camera chip counts").toLatin1().data()); + m_params.insert(paramVal.getName(), paramVal); + + paramVal = ito::Param( + "valueUnit", + ito::ParamBase::String, + "a.u.", + tr("unit of counts").toLatin1().data()); + m_params.insert(paramVal.getName(), paramVal); if (hasGuiSupport()) { - //now create dock widget for this plugin - DockWidgetDummyGrabber *dw = new DockWidgetDummyGrabber(this); + // now create dock widget for this plugin + DockWidgetDummyGrabber* dw = new DockWidgetDummyGrabber(this); Qt::DockWidgetAreas areas = Qt::AllDockWidgetAreas; - QDockWidget::DockWidgetFeatures features = QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable; - createDockWidget(QString(m_params["name"].getVal()), features, areas, dw); + QDockWidget::DockWidgetFeatures features = QDockWidget::DockWidgetClosable | + QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable; + createDockWidget(QString(m_params["name"].getVal()), features, areas, dw); } } @@ -383,24 +529,32 @@ DummyGrabber::~DummyGrabber() } //---------------------------------------------------------------------------------------------------------------------------------- -//! init method which is called by the addInManager after the initiation of a new instance of DummyGrabber. +//! init method which is called by the addInManager after the initiation of a new instance of +//! DummyGrabber. /*! - This init method gets the mandatory and optional parameter vectors of type tParam and must copy these given parameters to the - internal m_params-vector. Notice that this method is called after that this instance has been moved to its own (non-gui) thread. + This init method gets the mandatory and optional parameter vectors of type tParam and must copy + these given parameters to the internal m_params-vector. Notice that this method is called after + that this instance has been moved to its own (non-gui) thread. \param [in] paramsMand is a pointer to the vector of mandatory tParams. \param [in] paramsOpt is a pointer to the vector of optional tParams. - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk */ -ito::RetVal DummyGrabber::init(QVector * /*paramsMand*/, QVector *paramsOpt, ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::init( + QVector* /*paramsMand*/, + QVector* paramsOpt, + ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); ito::RetVal retVal; - int sizeX = paramsOpt->at(0).getVal(); // first optional parameter, corresponding to the grabber width - int sizeY = paramsOpt->at(1).getVal(); // second optional parameter, corresponding to the grabber heigth + int sizeX = paramsOpt->at(0) + .getVal(); // first optional parameter, corresponding to the grabber width + int sizeY = + paramsOpt->at(1) + .getVal(); // second optional parameter, corresponding to the grabber heigth if (sizeY > 1 && sizeY % 4 != 0) { @@ -408,7 +562,8 @@ ito::RetVal DummyGrabber::init(QVector * /*paramsMand*/, QVector } else { - int bpp = paramsOpt->at(2).getVal(); // third optional parameter, corresponding to the grabber bit depth per pixel + int bpp = paramsOpt->at(2).getVal(); // third optional parameter, corresponding to the + // grabber bit depth per pixel m_params["bpp"].setVal(bpp); m_params["sizex"].setVal(sizeX); @@ -430,17 +585,24 @@ ito::RetVal DummyGrabber::init(QVector * /*paramsMand*/, QVector m_params["roi"].setVal(roi, 4); if (sizeY == 1) { - m_params["roi"].setMeta(new ito::RectMeta(ito::RangeMeta(0, sizeX - 1, 4, 4, sizeX, 4), ito::RangeMeta(0, 0, 1)), true); + m_params["roi"].setMeta( + new ito::RectMeta( + ito::RangeMeta(0, sizeX - 1, 4, 4, sizeX, 4), ito::RangeMeta(0, 0, 1)), + true); } else { - m_params["roi"].setMeta(new ito::RectMeta(ito::RangeMeta(0, sizeX - 1, 4, 4, sizeX, 4), ito::RangeMeta(0, sizeY - 1, 4, 4, sizeY, 4)), true); + m_params["roi"].setMeta( + new ito::RectMeta( + ito::RangeMeta(0, sizeX - 1, 4, 4, sizeX, 4), + ito::RangeMeta(0, sizeY - 1, 4, 4, sizeY, 4)), + true); } } if (!retVal.containsError()) { - checkData(); //check if image must be reallocated + checkData(); // check if image must be reallocated emit parametersChanged(m_params); } @@ -469,7 +631,7 @@ ito::RetVal DummyGrabber::init(QVector * /*paramsMand*/, QVector waitCond->release(); } - setInitialized(true); //init method has been finished (independent on retval) + setInitialized(true); // init method has been finished (independent on retval) return retVal; } @@ -478,11 +640,10 @@ ito::RetVal DummyGrabber::init(QVector * /*paramsMand*/, QVector /*! notice that this method is called in the actual thread of this instance. - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk - \sa ItomSharedSemaphore + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk \sa ItomSharedSemaphore */ -ito::RetVal DummyGrabber::close(ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::close(ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); @@ -511,11 +672,11 @@ ito::RetVal DummyGrabber::close(ItomSharedSemaphore *waitCond) This method copies val of the corresponding parameter value. \param [in,out] val is a shared-pointer of ito::Param. - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk in case that everything is ok, else retError - \sa ito::tParam, ItomSharedSemaphore + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk in case that everything is ok, else retError \sa ito::tParam, + ItomSharedSemaphore */ -ito::RetVal DummyGrabber::getParam(QSharedPointer val, ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::getParam(QSharedPointer val, ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); ito::RetVal retValue; @@ -525,24 +686,25 @@ ito::RetVal DummyGrabber::getParam(QSharedPointer val, ItomSharedSem QString suffix; ParamMapIterator it; - //parse the given parameter-name (if you support indexed or suffix-based parameters) + // parse the given parameter-name (if you support indexed or suffix-based parameters) retValue += apiParseParamName(val->getName(), key, hasIndex, index, suffix); if (retValue == ito::retOk) { - //gets the parameter key from m_params map (read-only is allowed, since we only want to get the value). - retValue += apiGetParamFromMapByKey(m_params, key, it, false); + // gets the parameter key from m_params map (read-only is allowed, since we only want to get + // the value). + retValue += apiGetParamFromMapByKey(m_params, key, it, false); } if (!retValue.containsError()) { - *val = it.value(); + *val = it.value(); } if (waitCond) { - waitCond->returnValue = retValue; - waitCond->release(); + waitCond->returnValue = retValue; + waitCond->release(); } return retValue; @@ -554,11 +716,12 @@ ito::RetVal DummyGrabber::getParam(QSharedPointer val, ItomSharedSem This method copies the given value to the m_params-parameter. \param [in] val is the ito::ParamBase value to set. - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk in case that everything is ok, else retError - \sa ito::tParam, ItomSharedSemaphore + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk in case that everything is ok, else retError \sa ito::tParam, + ItomSharedSemaphore */ -ito::RetVal DummyGrabber::setParam(QSharedPointer val, ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::setParam( + QSharedPointer val, ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); ito::RetVal retValue; @@ -574,7 +737,8 @@ ito::RetVal DummyGrabber::setParam(QSharedPointer val, ItomShare if (!retValue.containsError()) { - //gets the parameter key from m_params map (read-only is not allowed and leads to ito::retError). + // gets the parameter key from m_params map (read-only is not allowed and leads to + // ito::retError). retValue += apiGetParamFromMapByKey(m_params, key, it, true); } @@ -585,7 +749,7 @@ ito::RetVal DummyGrabber::setParam(QSharedPointer val, ItomShare if (!retValue.containsError()) { - //first check parameters that influence the size or data type of m_data + // first check parameters that influence the size or data type of m_data if (key == "roi" || key == "binning" || key == "bpp") { if (!retValue.containsError()) @@ -627,11 +791,17 @@ ito::RetVal DummyGrabber::setParam(QSharedPointer val, ItomShare if (m_lineCamera && (newY != 1)) { - retValue += ito::RetVal(ito::retError, 0, "the vertical binning for a line camera must be 1"); + retValue += ito::RetVal( + ito::retError, 0, "the vertical binning for a line camera must be 1"); } - else if ((newX != 1 && newX != 2 && newX != 4) || (newY != 1 && newY != 2 && newY != 4)) + else if ( + (newX != 1 && newX != 2 && newX != 4) || (newY != 1 && newY != 2 && newY != 4)) { - retValue += ito::RetVal(ito::retError, 0, "horizontal and vertical binning must be 1, 2 or 4 (hence vertical * 100 + horizontal)"); + retValue += ito::RetVal( + ito::retError, + 0, + "horizontal and vertical binning must be 1, 2 or 4 (hence vertical * 100 + " + "horizontal)"); } else { @@ -653,10 +823,12 @@ ito::RetVal DummyGrabber::setParam(QSharedPointer val, ItomShare int maxHeight = m_params["sizey"].getMax(); m_params["sizex"].setVal(width); - m_params["sizex"].setMeta(new ito::IntMeta(4/newX, maxWidth * factorX, 4/newX), true); + m_params["sizex"].setMeta( + new ito::IntMeta(4 / newX, maxWidth * factorX, 4 / newX), true); m_params["sizey"].setVal(height); - m_params["sizey"].setMeta(new ito::IntMeta(4/newY, maxHeight * factorY, 4/newY), true); + m_params["sizey"].setMeta( + new ito::IntMeta(4 / newY, maxHeight * factorY, 4 / newY), true); int sizeX = m_params["roi"].getVal()[2] * factorX; int sizeY = m_params["roi"].getVal()[3] * factorY; @@ -664,12 +836,23 @@ ito::RetVal DummyGrabber::setParam(QSharedPointer val, ItomShare int offsetY = m_params["roi"].getVal()[1] * factorY; int roi[] = {offsetX, offsetY, sizeX, sizeY}; m_params["roi"].setVal(roi, 4); - m_params["roi"].setMeta(new ito::RectMeta(ito::RangeMeta(0, width - 1,4/newX,4/newX,maxWidth * factorX,4/newX), ito::RangeMeta(0, height - 1,4/newY,4/newY,maxHeight * factorY,4/newY)), true); + m_params["roi"].setMeta( + new ito::RectMeta( + ito::RangeMeta( + 0, width - 1, 4 / newX, 4 / newX, maxWidth * factorX, 4 / newX), + ito::RangeMeta( + 0, + height - 1, + 4 / newY, + 4 / newY, + maxHeight * factorY, + 4 / newY)), + true); } } } - retValue += checkData(); //check if image must be reallocated + retValue += checkData(); // check if image must be reallocated if (running) { @@ -685,6 +868,7 @@ ito::RetVal DummyGrabber::setParam(QSharedPointer val, ItomShare if (!retValue.containsError()) { + checkData(); emit parametersChanged(m_params); } @@ -700,19 +884,21 @@ ito::RetVal DummyGrabber::setParam(QSharedPointer val, ItomShare //---------------------------------------------------------------------------------------------------------------------------------- //! With startDevice this camera is initialized. /*! - In the DummyGrabber, this method does nothing. In general, the hardware camera should be intialized in this method and necessary memory should be allocated. + In the DummyGrabber, this method does nothing. In general, the hardware camera should be + intialized in this method and necessary memory should be allocated. \note This method is similar to VideoCapture::open() of openCV - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk if starting was successfull, retWarning if startDevice has been calling at least twice. + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk if starting was successfull, retWarning if startDevice has been calling + at least twice. */ -ito::RetVal DummyGrabber::startDevice(ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::startDevice(ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); ito::RetVal retValue = ito::retOk; - checkData(); //this will be reallocated in this method. + checkData(); // this will be reallocated in this method. incGrabberStarted(); @@ -734,15 +920,16 @@ ito::RetVal DummyGrabber::startDevice(ItomSharedSemaphore *waitCond) //---------------------------------------------------------------------------------------------------------------------------------- //! With stopDevice the camera device is stopped (opposite to startDevice) /*! - In this DummyGrabber, this method does nothing. In general, the hardware camera should be closed in this method. + In this DummyGrabber, this method does nothing. In general, the hardware camera should be closed + in this method. \note This method is similar to VideoCapture::release() of openCV - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk if everything is ok, retError if camera wasn't started before - \sa startDevice + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk if everything is ok, retError if camera wasn't started before \sa + startDevice */ -ito::RetVal DummyGrabber::stopDevice(ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::stopDevice(ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); ito::RetVal retValue = ito::retOk; @@ -750,7 +937,12 @@ ito::RetVal DummyGrabber::stopDevice(ItomSharedSemaphore *waitCond) decGrabberStarted(); if (grabberStartedCount() < 0) { - retValue += ito::RetVal(ito::retWarning, 1001, tr("stopDevice of DummyGrabber can not be executed, since camera has not been started.").toLatin1().data()); + retValue += ito::RetVal( + ito::retWarning, + 1001, + tr("stopDevice of DummyGrabber can not be executed, since camera has not been started.") + .toLatin1() + .data()); setGrabberStarted(0); } @@ -766,17 +958,18 @@ ito::RetVal DummyGrabber::stopDevice(ItomSharedSemaphore *waitCond) //---------------------------------------------------------------------------------------------------------------------------------- //! Call this method to trigger a new image. /*! - By this method a new image is trigger by the camera, that means the acquisition of the image starts in the moment, this method is called. - The new image is then stored either in internal camera memory or in internal memory of this class. + By this method a new image is trigger by the camera, that means the acquisition of the image + starts in the moment, this method is called. The new image is then stored either in internal + camera memory or in internal memory of this class. \note This method is similar to VideoCapture::grab() of openCV \param [in] trigger may describe the trigger parameter (unused here) - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk if everything is ok, retError if camera has not been started or an older image lies in memory which has not be fetched by getVal, yet. - \sa getVal + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk if everything is ok, retError if camera has not been started or an older + image lies in memory which has not be fetched by getVal, yet. \sa getVal */ -ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); ito::RetVal retValue = ito::retOk; @@ -800,7 +993,12 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa } else if (grabberStartedCount() <= 0) { - retValue += ito::RetVal(ito::retError, 1002, tr("Acquire of DummyGrabber can not be executed, since camera has not been started.").toLatin1().data()); + retValue += ito::RetVal( + ito::retError, + 1002, + tr("Acquire of DummyGrabber can not be executed, since camera has not been started.") + .toLatin1() + .data()); } else { @@ -817,19 +1015,18 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa } m_startOfLastAcquisition = cv::getTickCount(); - //ito::uint32 seed = m_startOfLastAcquisition % std::numeric_limits::max(); - cv::RNG &rng = cv::theRNG(); + // ito::uint32 seed = m_startOfLastAcquisition % std::numeric_limits::max(); + cv::RNG& rng = cv::theRNG(); if (m_imageType == imgTypeNoise) { - if (m_totalBinning == 1) { if (bpp < 9) { - ito::uint8 maxInt = cv::saturate_cast(cv::pow(2.0, bpp)-1); - ito::uint8 *linePtr; + ito::uint8 maxInt = cv::saturate_cast(cv::pow(2.0, bpp) - 1); + ito::uint8* linePtr; for (int m = 0; m < m_data.getSize(0); ++m) { @@ -843,8 +1040,8 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa } else if (bpp < 17) { - ito::uint16 maxInt = cv::saturate_cast(cv::pow(2.0, bpp)-1); - ito::uint16 *linePtr; + ito::uint16 maxInt = cv::saturate_cast(cv::pow(2.0, bpp) - 1); + ito::uint16* linePtr; for (int m = 0; m < m_data.getSize(0); ++m) { @@ -858,8 +1055,8 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa } else if (bpp < 32) { - ito::int32 maxInt = cv::saturate_cast(cv::pow(2.0, bpp)-1); - ito::int32 *linePtr; + ito::int32 maxInt = cv::saturate_cast(cv::pow(2.0, bpp) - 1); + ito::int32* linePtr; for (int m = 0; m < m_data.getSize(0); ++m) { @@ -876,8 +1073,8 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa { if (bpp < 9) { - ito::uint8 maxInt = cv::saturate_cast(cv::pow(2.0, bpp)-1); - ito::uint8 *linePtr; + ito::uint8 maxInt = cv::saturate_cast(cv::pow(2.0, bpp) - 1); + ito::uint8* linePtr; for (int m = 0; m < m_data.getSize(0); ++m) { @@ -885,14 +1082,15 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa for (int n = 0; n < m_data.getSize(1); ++n) { - *linePtr++ = fastrand_mean(rng, maxInt, m_totalBinning, offset, gain); + *linePtr++ = fastrand_mean( + rng, maxInt, m_totalBinning, offset, gain); } } } else if (bpp < 17) { - ito::uint16 maxInt = cv::saturate_cast(cv::pow(2.0, bpp)-1); - ito::uint16 *linePtr; + ito::uint16 maxInt = cv::saturate_cast(cv::pow(2.0, bpp) - 1); + ito::uint16* linePtr; for (int m = 0; m < m_data.getSize(0); ++m) { @@ -900,14 +1098,15 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa for (int n = 0; n < m_data.getSize(1); ++n) { - *linePtr++ = fastrand_mean(rng, maxInt,m_totalBinning, offset, gain); + *linePtr++ = fastrand_mean( + rng, maxInt, m_totalBinning, offset, gain); } } } else if (bpp < 32) { - ito::int32 maxInt = cv::saturate_cast(cv::pow(2.0, bpp)-1); - ito::int32 *linePtr; + ito::int32 maxInt = cv::saturate_cast(cv::pow(2.0, bpp) - 1); + ito::int32* linePtr; for (int m = 0; m < m_data.getSize(0); ++m) { @@ -915,18 +1114,15 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa for (int n = 0; n < m_data.getSize(1); ++n) { - *linePtr++ = fastrand_mean(rng, maxInt, m_totalBinning, offset, gain); + *linePtr++ = fastrand_mean( + rng, maxInt, m_totalBinning, offset, gain); } } } } - } - else if(m_imageType == imgTypeGaussianSpot) //create dummy Gaussian image + else if (m_imageType == imgTypeGaussianSpot) // create dummy Gaussian image { - - cv::RNG& rng = cv::theRNG(); - if (bpp < 9) { ito::uint8 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); @@ -943,10 +1139,9 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa gaussFunc(rng, m_data, amplitude); } } - else if (m_imageType == imgTypeGaussianSpotArray) //create dummy Gaussian image + else if (m_imageType == imgTypeGaussianSpotArray) // create dummy Gaussian image { ito::DataObject droi; - cv::RNG& rng = cv::theRNG(); int width = m_data.getSize(1); int height = m_data.getSize(0); @@ -954,10 +1149,11 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa int roiwidth = (int)width / 2; int roiheight = (int)height / 2; - int roi[4][4] = { { -0, -roiheight, -roiwidth, 0 }, - { -0, -roiheight, 0, -roiwidth }, - { -roiheight, 0, -roiwidth, 0 }, - { -roiheight, 0, 0, -roiwidth } }; + int roi[4][4] = { + {-0, -roiheight, -roiwidth, 0}, + {-0, -roiheight, 0, -roiwidth}, + {-roiheight, 0, -roiwidth, 0}, + {-roiheight, 0, 0, -roiwidth}}; for (int cnt = 0; cnt < 4; cnt++) { @@ -980,92 +1176,6 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa gaussFunc(rng, droi, amplitude); } } - - - - - //// take 1 rechts oben - //droi = droi.adjustROI(- 0, - roiheight, -roiwidth, 0); // rechts unten - - //if (bpp < 9) - //{ - // ito::uint8 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - //else if (bpp < 17) - //{ - // ito::uint16 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - //else if (bpp < 32) - //{ - // ito::uint32 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - - //// take 2 - //droi = m_data; - //droi = droi.adjustROI(-0, -roiheight, 0, - roiwidth); // links unten - - //if (bpp < 9) - //{ - // ito::uint8 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - //else if (bpp < 17) - //{ - // ito::uint16 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - //else if (bpp < 32) - //{ - // ito::uint32 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - - //// take 3 - //droi = m_data; - //droi = droi.adjustROI(- roiheight, 0, - roiwidth, 0); // rechts oben - - //if (bpp < 9) - //{ - // ito::uint8 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - //else if (bpp < 17) - //{ - // ito::uint16 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - //else if (bpp < 32) - //{ - // ito::uint32 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - - //// take 4 - //droi = m_data; - //droi = droi.adjustROI(-roiheight, 0, 0, -roiwidth); // links oben - - //if (bpp < 9) - //{ - // ito::uint8 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - //else if (bpp < 17) - //{ - // ito::uint16 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - //else if (bpp < 32) - //{ - // ito::uint32 amplitude = cv::saturate_cast(cv::pow(2.0, bpp) - 1); - // gaussFunc(rng, droi, amplitude); - //} - - - - } if (integration_time > 0.0) @@ -1089,15 +1199,16 @@ ito::RetVal DummyGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore *wa \note This method is similar to VideoCapture::retrieve() of openCV - \param [in,out] vpdObj is the pointer to a given dataObject (this pointer should be cast to ito::DataObject*) where the acquired image is shallow-copied to. - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk if everything is ok, retError is camera has not been started or no image has been acquired by the method acquire. - \sa DataObject, acquire + \param [in,out] vpdObj is the pointer to a given dataObject (this pointer should be cast to + ito::DataObject*) where the acquired image is shallow-copied to. \param [in] waitCond is the + semaphore (default: NULL), which is released if this method has been terminated \return retOk if + everything is ok, retError is camera has not been started or no image has been acquired by the + method acquire. \sa DataObject, acquire */ -ito::RetVal DummyGrabber::getVal(void *vpdObj, ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::getVal(void* vpdObj, ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); - ito::DataObject *dObj = reinterpret_cast(vpdObj); + ito::DataObject* dObj = reinterpret_cast(vpdObj); ito::RetVal retValue(ito::retOk); @@ -1107,11 +1218,15 @@ ito::RetVal DummyGrabber::getVal(void *vpdObj, ItomSharedSemaphore *waitCond) { if (dObj == NULL) { - retValue += ito::RetVal(ito::retError, 1004, tr("data object of getVal is NULL or cast failed").toLatin1().data()); + retValue += ito::RetVal( + ito::retError, + 1004, + tr("data object of getVal is NULL or cast failed").toLatin1().data()); } else { - retValue += sendDataToListeners(0); //don't wait for live image, since user should get the image as fast as possible. + retValue += sendDataToListeners(0); // don't wait for live image, since user should get + // the image as fast as possible. (*dObj) = this->m_data; } @@ -1119,7 +1234,7 @@ ito::RetVal DummyGrabber::getVal(void *vpdObj, ItomSharedSemaphore *waitCond) if (waitCond) { - waitCond->returnValue=retValue; + waitCond->returnValue = retValue; waitCond->release(); } @@ -1129,25 +1244,27 @@ ito::RetVal DummyGrabber::getVal(void *vpdObj, ItomSharedSemaphore *waitCond) //---------------------------------------------------------------------------------------------------------------------------------- //! Returns the grabbed camera frame as a deep copy. /*! - This method copies the recently grabbed camera frame to the given DataObject. Therefore this camera size must fit to the data structure of the - DataObject. + This method copies the recently grabbed camera frame to the given DataObject. Therefore this + camera size must fit to the data structure of the DataObject. \note This method is similar to VideoCapture::retrieve() of openCV - \param [in,out] vpdObj is the pointer to a given dataObject (this pointer should be cast to ito::DataObject*) where the acquired image is deep copied to. - \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been terminated - \return retOk if everything is ok, retError is camera has not been started or no image has been acquired by the method acquire. - \sa DataObject, acquire + \param [in,out] vpdObj is the pointer to a given dataObject (this pointer should be cast to + ito::DataObject*) where the acquired image is deep copied to. \param [in] waitCond is the + semaphore (default: NULL), which is released if this method has been terminated \return retOk if + everything is ok, retError is camera has not been started or no image has been acquired by the + method acquire. \sa DataObject, acquire */ -ito::RetVal DummyGrabber::copyVal(void *vpdObj, ItomSharedSemaphore *waitCond) +ito::RetVal DummyGrabber::copyVal(void* vpdObj, ItomSharedSemaphore* waitCond) { ItomSharedSemaphoreLocker locker(waitCond); ito::RetVal retValue(ito::retOk); - ito::DataObject *dObj = reinterpret_cast(vpdObj); + ito::DataObject* dObj = reinterpret_cast(vpdObj); if (!dObj) { - retValue += ito::RetVal(ito::retError, 0, tr("Empty object handle retrieved from caller").toLatin1().data()); + retValue += ito::RetVal( + ito::retError, 0, tr("Empty object handle retrieved from caller").toLatin1().data()); } else { @@ -1161,7 +1278,8 @@ ito::RetVal DummyGrabber::copyVal(void *vpdObj, ItomSharedSemaphore *waitCond) if (!retValue.containsError()) { - sendDataToListeners(0); //don't wait for live image, since user should get the image as fast as possible. + sendDataToListeners( + 0); // don't wait for live image, since user should get the image as fast as possible. } if (waitCond) @@ -1174,13 +1292,16 @@ ito::RetVal DummyGrabber::copyVal(void *vpdObj, ItomSharedSemaphore *waitCond) } //---------------------------------------------------------------------------------------------------------------------------------- -ito::RetVal DummyGrabber::retrieveData(ito::DataObject *externalDataObject) +ito::RetVal DummyGrabber::retrieveData(ito::DataObject* externalDataObject) { ito::RetVal retValue(ito::retOk); if (m_isgrabbing == false) { - retValue += ito::RetVal(ito::retError, 1002, tr("image could not be obtained since no image has been acquired.").toLatin1().data()); + retValue += ito::RetVal( + ito::retError, + 1002, + tr("image could not be obtained since no image has been acquired.").toLatin1().data()); } else { @@ -1200,15 +1321,23 @@ void DummyGrabber::dockWidgetVisibilityChanged(bool visible) { if (getDockWidget()) { - QWidget *widget = getDockWidget()->widget(); + QWidget* widget = getDockWidget()->widget(); if (visible) { - connect(this, SIGNAL(parametersChanged(QMap)), widget, SLOT(parametersChanged(QMap))); + connect( + this, + SIGNAL(parametersChanged(QMap)), + widget, + SLOT(parametersChanged(QMap))); emit parametersChanged(m_params); } else { - disconnect(this, SIGNAL(parametersChanged(QMap)), widget, SLOT(parametersChanged(QMap))); + disconnect( + this, + SIGNAL(parametersChanged(QMap)), + widget, + SLOT(parametersChanged(QMap))); } } } diff --git a/DummyGrabber/docs/dummyGrabber.rst b/DummyGrabber/docs/dummyGrabber.rst index 9334b69b..1c413c1d 100644 --- a/DummyGrabber/docs/dummyGrabber.rst +++ b/DummyGrabber/docs/dummyGrabber.rst @@ -30,6 +30,18 @@ Parameters An instance of this plugin has the following parameters: +**axisDescription**: Sequence[str] + axis description +**axisOffset**: Sequence[float] + axis offset + + *2 values required, All values allowed, Default: [0, 0]* +**axisScale**: Sequence[float] + axis scale + + *2 values required, All values allowed, Default: [0.001, 0.001]* +**axisUnit**: Sequence[str] + axis unit **binning**: int Binning of different pixel, binning = x-factor * 100 + y-factor @@ -54,7 +66,7 @@ An instance of this plugin has the following parameters: **demoRegexpString**: str matches strings without whitespaces - *RegExp: "^\S+$", Default: * + *RegularExpression: "^\S+$", Default: * **demoWildcardString**: str dummy filename of a bmp file, pattern: *.bmp @@ -82,12 +94,16 @@ An instance of this plugin has the following parameters: **roi**: Tuple[int,int,int,int] (rect [x0,y0,width,height]) ROI (x,y,width,height) [this replaces the values x0,x1,y0,y1] - *Height: Value range: [0:4:479], Default: [0, 0, 640, 480]* + *Height: Value range: [0:4:479], Default: [100, 40, 400, 300]* **sizex**: int, read-only size in x (cols) [px] - *Value range: [4:4:640], Default: 640* + *Value range: [4:4:640], Default: 400* **sizey**: int, read-only size in y (rows) [px] - *Value range: [4:4:480], Default: 480* + *Value range: [4:4:480], Default: 300* +**valueDescription**: str + camera chip counts +**valueUnit**: str + unit of counts diff --git a/DummyMultiChannelGrabber/CMakeLists.txt b/DummyMultiChannelGrabber/CMakeLists.txt new file mode 100644 index 00000000..8a244dfd --- /dev/null +++ b/DummyMultiChannelGrabber/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.12...3.24) + +set(target_name DummyMultiChannelGrabber) + +option(BUILD_TARGET64 "Build for 64 bit target if set to ON or 32 bit if set to OFF." ON) +set(ITOM_SDK_DIR NOTFOUND CACHE PATH "path of SDK subfolder of itom root (build) directory") + +#this is to automatically detect the SDK subfolder of the itom build directory. +find_path(ITOM_SDK_DIR "cmake/itom_sdk.cmake" + HINTS "C:/itom/build/itom/SDK" + "${CMAKE_CURRENT_BINARY_DIR}/../../itom/SDK" + DOC "path of SDK subfolder of itom root (build) directory") + +if(NOT ITOM_SDK_DIR) + message(SEND_ERROR "ITOM_SDK_DIR is invalid. Provide itom SDK directory path first") +endif() + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${ITOM_SDK_DIR}/cmake) + +include(ItomBuildMacros) +itom_init_cmake_policy(3.12) +itom_init_plugin_library(${target_name}) #Start the project, init compiler settings and set default configurations for plugins + + +find_package(ITOM_SDK COMPONENTS dataobject itomCommonLib itomCommonQtLib itomWidgets REQUIRED) +itom_find_package_qt(ON Core Widgets LinguistTools) + +find_package(OpenCV COMPONENTS core REQUIRED) + + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${ITOM_SDK_INCLUDE_DIRS} + ) + +set(PLUGIN_HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/dialogDummyMultiChannelGrabber.h + ${CMAKE_CURRENT_SOURCE_DIR}/dockWidgetDummyMultiChannelGrabber.h + ${CMAKE_CURRENT_SOURCE_DIR}/dummyMultiChannelGrabber.h + ${CMAKE_CURRENT_SOURCE_DIR}/dummyMultiChannelGrabberInterface.h + ${CMAKE_CURRENT_SOURCE_DIR}/cameraEmulator.h + ${CMAKE_CURRENT_SOURCE_DIR}/pluginVersion.h + ${CMAKE_CURRENT_BINARY_DIR}/gitVersion.h +) + +set(PLUGIN_UI + ${CMAKE_CURRENT_SOURCE_DIR}/dialogDummyMultiChannelGrabber.ui + ${CMAKE_CURRENT_SOURCE_DIR}/dockWidgetDummyMultiChannelGrabber.ui +) + +set(PLUGIN_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/dialogDummyMultiChannelGrabber.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dockWidgetDummyMultiChannelGrabber.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dummyMultiChannelGrabber.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dummyMultiChannelGrabberInterface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cameraEmulator.cpp +) + +#Add version information to the plugIn-dll unter MSVC +if(MSVC) + list(APPEND PLUGIN_SOURCES ${ITOM_SDK_INCLUDE_DIR}/../pluginLibraryVersion.rc) +endif() + +################################################################# +# Qt related pre-processing of the files above +# (These methods create the moc, rcc and uic process.) +################################################################# + + +add_library(${target_name} SHARED ${PLUGIN_SOURCES} ${PLUGIN_HEADERS} ${PLUGIN_UI} ${PLUGIN_RCC}) + +# Qt: enable all automoc, autouic and autorcc. +set_target_properties(${target_name} PROPERTIES AUTOMOC ON AUTORCC ON AUTOUIC ON) + +target_link_libraries(${target_name} ${ITOM_SDK_LIBRARIES} ${QT5_LIBRARIES} ${VISUALLEAKDETECTOR_LIBRARIES} ${QT_LIBRARIES}) + + + +#translation +set(FILES_TO_TRANSLATE ${PLUGIN_SOURCES} ${PLUGIN_HEADERS} ${PLUGIN_UI}) +itom_library_translation(QM_FILES TARGET ${target_name} FILES_TO_TRANSLATE ${FILES_TO_TRANSLATE}) + +itom_configure_plugin_documentation(${target_name} DummyMultiChannelGrabber) + +# COPY SECTION +set(COPY_SOURCES "") +set(COPY_DESTINATIONS "") + +itom_add_pluginlibrary_to_copy_list(${target_name} COPY_SOURCES COPY_DESTINATIONS) + +itom_add_plugin_qm_files_to_copy_list(${target_name} QM_FILES COPY_SOURCES COPY_DESTINATIONS) +itom_post_build_copy_files(${target_name} COPY_SOURCES COPY_DESTINATIONS) diff --git a/DummyMultiChannelGrabber/cameraEmulator.cpp b/DummyMultiChannelGrabber/cameraEmulator.cpp new file mode 100644 index 00000000..e705dc12 --- /dev/null +++ b/DummyMultiChannelGrabber/cameraEmulator.cpp @@ -0,0 +1,242 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#include "cameraEmulator.h" + +#include +#include + +//------------------------------------------------------------------------------------- +/** @func fastrand + * @brief function for pseudo random values + * + * This function delivers the noise for the image. + */ +template inline _Tp fastrand(cv::RNG& rng, _Tp maxval, float offset, float gain) +{ + return cv::saturate_cast<_Tp>(offset * maxval + gain * (((ito::uint32)rng.next()) & maxval)); +} + +//------------------------------------------------------------------------------------- +/** @func fastrand + * @brief function for pseudo random values + * + * This function delivers the noise for the image. + */ +template +inline _Tp fastrand_mean(cv::RNG& rng, _Tp maxval, ito::uint8 numMeans, float offset, float gain) +{ + ito::uint32 val = 0; + + for (ito::uint8 i = 0; i < numMeans; ++i) + { + val += ((ito::uint32)rng.next()) & maxval; + } + + return cv::saturate_cast<_Tp>(offset * maxval + (gain / (float)numMeans) * val); +} + +//------------------------------------------------------------------------------------- +/** @func gaussFunc + * @brief function for 2d Gaussian function + * + * This function delivers a 2d dataObject with a Gaussian function + */ +template ito::RetVal gaussFunc(cv::RNG& rng, ito::DataObject &dObj, float amplitude) +{ + int width = dObj.getSize(1); + int height = dObj.getSize(0); + _Tp* rowPtr; + float xval, yval; + int planeID = dObj.seekMat(0); + + float yRandOffset = rng.uniform(0.f, 20.f); + float xRandOffset = rng.uniform(0.f, 20.f); + float aRandOfset = rng.uniform(-amplitude * 0.1, amplitude * 0.1); + + float sigmaX = width * rng.uniform(0.09f, 0.11f); + float sigmaY = height * rng.uniform(0.09f, 0.11f); + + for (int y = 0; y < height; y++) + { + rowPtr = dObj.rowPtr<_Tp>(planeID, y); + yval = (((float)y - height / 2 + yRandOffset) * ((float)y - height / 2 + yRandOffset)) / + (2.0f * sigmaY * sigmaY); + + for (int x = 0; x < width; x++) + { + xval = (((float)x - width / 2 + xRandOffset) * ((float)x - width / 2 + xRandOffset)) / + (2.0f * sigmaX * sigmaX); + rowPtr[x] = (float)(amplitude - aRandOfset) * exp(-(xval + yval)); + } + } + + return ito::retOk; +} + + + +//------------------------------------------------------------------------------------- +CameraEmulator::CameraEmulator() : + m_imageColorAlpha(false), + m_imageMonoBpp(8) +{ + +} + +//------------------------------------------------------------------------------------- +void CameraEmulator::configureImageMono(const QRect& roi, int bpp) +{ + int h = roi.height(); + int w = roi.width(); + + switch (bpp) + { + case 8: + m_imageMonoBpp = 8; + m_imageMono = ito::DataObject(h, w, ito::tUInt8); + break; + case 10: + m_imageMonoBpp = 10; + m_imageMono = ito::DataObject(h, w, ito::tUInt16); + break; + case 12: + m_imageMonoBpp = 12; + m_imageMono = ito::DataObject(h, w, ito::tUInt16); + break; + case 16: + m_imageMonoBpp = 16; + m_imageMono = ito::DataObject(h, w, ito::tUInt16); + default: + break; + } +} + +//------------------------------------------------------------------------------------- +void CameraEmulator::configureImageTopography(const QRect& roi, bool singlePrecision) +{ + int h = roi.height(); + int w = roi.width(); + + if (singlePrecision) + { + m_imageTopography = ito::DataObject(h, w, ito::tFloat32); + } + else + { + m_imageTopography = ito::DataObject(h, w, ito::tFloat64); + } +} + +//------------------------------------------------------------------------------------- +void CameraEmulator::configureImageColor(const QRect& roi, bool alpha) +{ + int h = roi.height(); + int w = roi.width(); + m_imageColorAlpha = alpha; + + m_imageColor = ito::DataObject(h, w, ito::tRGBA32); +} + +//------------------------------------------------------------------------------------- +bool CameraEmulator::grabImages(bool imgMono, bool imgFloat, bool imgColor, float exposureTimeMs) +{ + bool result = true; + QElapsedTimer timer; + timer.start(); + + if (imgMono) + { + result &= grabMono(); + } + + if (imgFloat) + { + result &= grabTopography(); + } + + if (imgColor) + { + result &= grabColor(); + } + + exposureTimeMs -= timer.elapsed(); + + if (exposureTimeMs > 0) + { + QThread::usleep(1000 * exposureTimeMs); + } + + return result; +} + +//------------------------------------------------------------------------------------- +bool CameraEmulator::grabMono() +{ + const unsigned int low = 0; + const unsigned int high = std::pow(m_imageMonoBpp, 2) - 1; + + cv::randu(*(m_imageMono.getCvPlaneMat(0)), low, high); + + return true; +} + +//------------------------------------------------------------------------------------- +bool CameraEmulator::grabTopography() +{ + cv::RNG& rng = cv::theRNG(); + + if (m_imageTopography.getType() == ito::tFloat32) + { + gaussFunc(rng, m_imageTopography, 10.0); + } + else + { + gaussFunc(rng, m_imageTopography, 10.0); + } + + return true; +} + +//------------------------------------------------------------------------------------- +bool CameraEmulator::grabColor() +{ + cv::Mat* mat = m_imageColor.getCvPlaneMat(0); + ito::uint32* rowPtr; + + for (int r = 0; r < mat->rows; ++r) + { + rowPtr = mat->ptr(r); + + for (int c = 0; c < mat->cols; ++c) + { + rowPtr[c] = cv::randu(); + + if (!m_imageColorAlpha) + { + ((ito::Rgba32*)rowPtr)[c].a = 255; + } + } + } + + return true; +} diff --git a/DummyMultiChannelGrabber/cameraEmulator.h b/DummyMultiChannelGrabber/cameraEmulator.h new file mode 100644 index 00000000..489e48f6 --- /dev/null +++ b/DummyMultiChannelGrabber/cameraEmulator.h @@ -0,0 +1,57 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#pragma once + +#include +#include +#include "DataObject/dataobj.h" + +class CameraEmulator : public QObject +{ +public: + explicit CameraEmulator(); + + const ito::DataObject& imageMono() const { return m_imageMono; } + const ito::DataObject& imageTopography() const { return m_imageTopography; } + const ito::DataObject& imageColor() const { return m_imageColor; } + + void configureImageMono(const QRect &roi, int bpp); + void configureImageTopography(const QRect& roi, bool singlePrecision); + void configureImageColor(const QRect& roi, bool alpha); + + bool grabImages(bool imgMono, bool imgFloat, bool imgColor, float exposureTimeMs); + +private: + bool grabMono(); + bool grabTopography(); + bool grabColor(); + + QRect m_roiMono; + QRect m_roiTopography; + QRect m_roiColor; + ito::DataObject m_imageMono; + ito::DataObject m_imageTopography; + ito::DataObject m_imageColor; + int m_imageMonoBpp; + bool m_imageColorAlpha; +}; diff --git a/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.cpp b/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.cpp new file mode 100644 index 00000000..62937607 --- /dev/null +++ b/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.cpp @@ -0,0 +1,288 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#include "dialogDummyMultiChannelGrabber.h" + +#include +#include +#include + + +//---------------------------------------------------------------------------------------------------------------------------------- +DialogDummyMultiChannelGrabber::DialogDummyMultiChannelGrabber(ito::AddInBase *grabber) : + AbstractAddInConfigDialog(grabber), + m_firstRun(true) +{ + ui.setupUi(this); + + //disable dialog, since no parameters are known. Parameters will immediately be sent by the slot parametersChanged. + enableDialog(false); +}; + + +//---------------------------------------------------------------------------------------------------------------------------------- +void DialogDummyMultiChannelGrabber::parametersChanged(QMap params) +{ + m_currentParameters = params; + + if (m_firstRun) + { + setWindowTitle(QString((params)["name"].getVal()) + " - " + tr("Configuration Dialog")); + + ito::IntMeta *bppMeta = static_cast(params["pixelFormat"].getMeta()); + ui.combo_bpp->clear(); + int count = 0; + for (int i = bppMeta->getMin(); i <= bppMeta->getMax(); i += bppMeta->getStepSize()) + { + ui.combo_bpp->addItem(QString::number(i)); + ui.combo_bpp->setItemData(count++, i, Qt::UserRole); + } + + ui.comboBinningX->clear(); + ui.comboBinningX->addItem(QString::number(1), 1); + ui.comboBinningX->addItem(QString::number(2), 2); + ui.comboBinningX->addItem(QString::number(4), 4); + + ui.comboBinningY->clear(); + ui.comboBinningY->addItem(QString::number(1), 1); + ui.comboBinningY->addItem(QString::number(2), 2); + ui.comboBinningY->addItem(QString::number(4), 4); + + ui.doubleSpinBox_integration_time->setDisabled( params["integration_time"].getFlags() & ito::ParamBase::Readonly ); + ui.doubleSpinBox_frame_time->setDisabled( params["frame_time"].getFlags() & ito::ParamBase::Readonly ); + + m_firstRun = false; + } + + ito::RectMeta *rm = static_cast(params["roi"].getMeta()); + ui.rangeX01->setLimitsFromIntervalMeta(rm->getWidthRangeMeta()); + ui.rangeY01->setLimitsFromIntervalMeta(rm->getHeightRangeMeta()); + + int *roi = params["roi"].getVal(); + ui.rangeX01->setValues(roi[0], roi[0] + roi[2] - 1); + ui.rangeY01->setValues(roi[1], roi[1] + roi[3] - 1); + ui.rangeX01->setEnabled(! (params["roi"].getFlags() & ito::ParamBase::Readonly)); + ui.rangeY01->setEnabled((!(params["roi"].getFlags() & ito::ParamBase::Readonly)) && params["sizey"].getMax() > 1); + + ui.spinSizeX->setValue(params["sizex"].getVal()); + ui.spinSizeY->setValue(params["sizey"].getVal()); + + double dval = params["gain"].getVal(); + ui.sliderGain->setValue(dval*100.0); + ui.sliderGain->setEnabled(!(params["gain"].getFlags() & ito::ParamBase::Readonly)); + ui.spinBox_gain->setEnabled(!(params["gain"].getFlags() & ito::ParamBase::Readonly)); + + dval = params["offset"].getVal(); + ui.sliderOffset->setValue(dval*100.0); + ui.sliderOffset->setEnabled(!(params["offset"].getFlags() & ito::ParamBase::Readonly)); + ui.spinBox_offset->setEnabled(!(params["gain"].getFlags() & ito::ParamBase::Readonly)); + + ui.combo_bpp->setEnabled(!(params["pixelFormat"].getFlags() & ito::ParamBase::Readonly)); + + for (int i = 0; i < ui.combo_bpp->count(); ++i) + { + if (ui.combo_bpp->itemData(i, Qt::UserRole).toInt() == params["pixelFormat"].getVal()) + { + ui.combo_bpp->setCurrentIndex(i); + break; + } + } + + int ival = params["binning"].getVal(); + int ivalY = ival % 100; + int ivalX = (ival - ivalY) / 100; + ui.comboBinningX->setEnabled(!(params["binning"].getFlags() & ito::ParamBase::Readonly)); + ui.comboBinningY->setEnabled(!(params["binning"].getFlags() & ito::ParamBase::Readonly)); + + int idx = ui.comboBinningX->findData(ivalX, Qt::UserRole); + if (idx >= 0) + { + ui.comboBinningX->setCurrentIndex(idx); + } + + idx = ui.comboBinningY->findData(ivalY, Qt::UserRole); + if (idx >= 0) + { + ui.comboBinningY->setCurrentIndex(idx); + } + + ui.doubleSpinBox_integration_time->setMaximum(params["integration_time"].getMax() *1000.0); + ui.doubleSpinBox_integration_time->setMinimum(params["integration_time"].getMin() *1000.0); + ui.doubleSpinBox_integration_time->setSingleStep(1.0); + ui.doubleSpinBox_integration_time->setValue(params["integration_time"].getVal() *1000.0); + + ui.doubleSpinBox_frame_time->setMaximum(params["frame_time"].getMax() *1000.0); + ui.doubleSpinBox_frame_time->setMinimum(params["frame_time"].getMin() *1000.0); + ui.doubleSpinBox_frame_time->setSingleStep(1.0); + ui.doubleSpinBox_frame_time->setValue(params["frame_time"].getVal() *1000.0); + + + //now activate group boxes, since information is available now (at startup, information is not available, since parameters are sent by a signal) + enableDialog(true); +} + +//---------------------------------------------------------------------------------------------------------------------------------- +ito::RetVal DialogDummyMultiChannelGrabber::applyParameters() +{ + ito::RetVal retValue(ito::retOk); + QVector > values; + bool success = false; + + if (ui.rangeX01->isEnabled() || ui.rangeY01->isEnabled()) + { + int x0, x1, y0, y1; + ui.rangeX01->values(x0,x1); + if (ui.rangeY01->isEnabled()) + { + ui.rangeY01->values(y0,y1); + } + else + { + y0 = 0; + y1 = 0; + } + + int roi[] = {0,0,0,0}; + memcpy(roi, m_currentParameters["roi"].getVal(), 4*sizeof(int)); + + if (roi[0] != x0 || roi[1] != y0 || roi[2] != (x1-x0+1) || roi[3] != (y1-y0+1)) + { + roi[0] = x0; + roi[1] = y0; + roi[2] = x1-x0+1; + roi[3] = y1-y0+1; + values.append(QSharedPointer(new ito::ParamBase("roi", ito::ParamBase::IntArray, 4, roi))); + } + } + + if (ui.comboBinningX->isEnabled() && ui.comboBinningY->isEnabled()) + { + int bin = ui.comboBinningX->currentText().toInt() * 100 + ui.comboBinningY->currentText().toInt(); + if (m_currentParameters["binning"].getVal() != bin) + { + values.append(QSharedPointer(new ito::ParamBase("binning", ito::ParamBase::Int, bin))); + } + } + + if (ui.sliderGain->isEnabled()) + { + double dval = ui.sliderGain->value()/100.0; + if (qAbs(m_currentParameters["gain"].getVal() - dval) >= std::numeric_limits::epsilon()) + { + values.append(QSharedPointer(new ito::ParamBase("gain", ito::ParamBase::Double, dval))); + } + } + + if (ui.sliderOffset->isEnabled()) + { + double dval = ui.sliderOffset->value()/100.0; + if (qAbs(m_currentParameters["offset"].getVal() - dval) >= std::numeric_limits::epsilon()) + { + values.append(QSharedPointer(new ito::ParamBase("offset", ito::ParamBase::Double, dval))); + } + } + + if (ui.doubleSpinBox_integration_time->isEnabled()) + { + double dval = ui.doubleSpinBox_integration_time->value(); + if (qAbs(m_currentParameters["integration_time"].getVal() - dval) >= 0.00001) //the smallest range is 1musec, given by the number of decimals of the spin box. //std::numeric_limits::epsilon()) + { + values.append(QSharedPointer(new ito::ParamBase("integration_time", ito::ParamBase::Double, dval))); + } + } + + if (ui.doubleSpinBox_frame_time->isEnabled()) + { + double dval = ui.doubleSpinBox_frame_time->value(); + if (qAbs(m_currentParameters["frame_time"].getVal() - dval) >= 0.00001) //the smallest range is 1musec, given by the number of decimals of the spin box. //std::numeric_limits::epsilon()) + { + values.append(QSharedPointer(new ito::ParamBase("frame_time", ito::ParamBase::Double, dval))); + } + } + + if (ui.combo_bpp->isEnabled()) + { + int bpp = ui.combo_bpp->itemData(ui.combo_bpp->currentIndex()).toInt(); + + if (m_currentParameters["pixelFormat"].getVal() != bpp) + { + values.append(QSharedPointer(new ito::ParamBase("pixelFormat", ito::ParamBase::Int, bpp))); + } + } + + + + retValue += setPluginParameters(values, msgLevelWarningAndError); + + return retValue; +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogDummyMultiChannelGrabber::on_buttonBox_clicked(QAbstractButton* btn) +{ + ito::RetVal retValue(ito::retOk); + + QDialogButtonBox::ButtonRole role = ui.buttonBox->buttonRole(btn); + + if (role == QDialogButtonBox::RejectRole) + { + reject(); //close dialog with reject + } + else if (role == QDialogButtonBox::AcceptRole) + { + accept(); //AcceptRole + } + else + { + applyParameters(); //ApplyRole + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogDummyMultiChannelGrabber::enableDialog(bool enabled) +{ + ui.groupBoxBinning->setEnabled(enabled); + ui.groupBoxIntegration->setEnabled(enabled); + ui.groupBoxSize->setEnabled(enabled); +} + +//---------------------------------------------------------------------------------------------------------------------------------- +void DialogDummyMultiChannelGrabber::on_rangeX01_valuesChanged(int minValue, int maxValue) +{ + ui.spinSizeX->setValue(maxValue - minValue + 1); +} + +//---------------------------------------------------------------------------------------------------------------------------------- +void DialogDummyMultiChannelGrabber::on_rangeY01_valuesChanged(int minValue, int maxValue) +{ + ui.spinSizeY->setValue(maxValue - minValue + 1); +} + +//---------------------------------------------------------------------------------------------------------------------------------- +void DialogDummyMultiChannelGrabber::on_btnFullROI_clicked() +{ + if (m_currentParameters.contains("sizex") && m_currentParameters.contains("sizey")) + { + ui.rangeX01->setValues(0, m_currentParameters["sizex"].getMax()); + ui.rangeY01->setValues(0, m_currentParameters["sizey"].getMax()); + } +} diff --git a/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.h b/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.h new file mode 100644 index 00000000..6c3746fa --- /dev/null +++ b/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.h @@ -0,0 +1,66 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#ifndef DIALOGDummyMultiChannelGrabber_H +#define DIALOGDummyMultiChannelGrabber_H + +#include "common/param.h" +#include "common/retVal.h" +#include "common/sharedStructuresQt.h" +#include "common/abstractAddInConfigDialog.h" + +#include "ui_dialogDummyMultiChannelGrabber.h" + +namespace ito +{ + class AddInBase; //forward declaration +} + +class DialogDummyMultiChannelGrabber : public ito::AbstractAddInConfigDialog +{ + Q_OBJECT + + public: + DialogDummyMultiChannelGrabber(ito::AddInBase *grabber); + ~DialogDummyMultiChannelGrabber() {}; + + ito::RetVal applyParameters(); + private: + void enableDialog(bool enabled); + + Ui::dialogDummyMultiChannelGrabber ui; + bool m_firstRun; + + signals: + + public slots: + + void parametersChanged(QMap params); + + private slots: + void on_buttonBox_clicked(QAbstractButton* btn); + void on_rangeX01_valuesChanged(int minValue, int maxValue); + void on_rangeY01_valuesChanged(int minValue, int maxValue); + void on_btnFullROI_clicked(); +}; + +#endif diff --git a/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.ui b/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.ui new file mode 100644 index 00000000..7aba086f --- /dev/null +++ b/DummyMultiChannelGrabber/dialogDummyMultiChannelGrabber.ui @@ -0,0 +1,623 @@ + + + dialogDummyMultiChannelGrabber + + + + 0 + 0 + 606 + 498 + + + + Dialog + + + + + + + + true + + + Buffer + + + + + + + + + 0 + 0 + + + + Binning X + + + + + + + + 1 + + + + + 2 + + + + + 4 + + + + + + + + + 0 + 0 + + + + Binning Y + + + + + + + + 1 + + + + + 2 + + + + + 4 + + + + + + + + + + + + Bits per Pixel + + + + + + + false + + + -1 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + true + + + Integration + + + + + + Offset + + + + + + + false + + + 100 + + + false + + + Qt::Horizontal + + + + + + + false + + + % + + + 0 + + + 100 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 13 + 20 + + + + + + + + Gain + + + + + + + false + + + 100 + + + false + + + Qt::Horizontal + + + + + + + false + + + % + + + 0 + + + 100 + + + + + + + Integrationtime + + + + + + + false + + + + + + ms + + + 1 + + + 0.000000000000000 + + + 65.000000000000000 + + + 1.000000000000000 + + + 10.000000000000000 + + + + + + + Frametime + + + + + + + false + + + + + + ms + + + 1 + + + 0.000000000000000 + + + 65.000000000000000 + + + 1.000000000000000 + + + 10.000000000000000 + + + + + + + + + + true + + + Size + + + + + + + + x0 + + + + + + + 2048 + + + 99 + + + + + + + + + 5 + + + true + + + false + + + 0 + + + + + + + x1 + + + + + + + y0 + + + + + + + 2 + + + 2048 + + + 99 + + + + + + + + + 5 + + + true + + + false + + + 0 + + + + + + + y1 + + + + + + + + + + + x-size + + + + + + + true + + + true + + + QAbstractSpinBox::NoButtons + + + false + + + px + + + 10000 + + + 666 + + + + + + + y-size + + + + + + + true + + + true + + + QAbstractSpinBox::NoButtons + + + px + + + 10000 + + + 666 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + full ROI + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Qt::Vertical + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + RangeWidget + QWidget +
rangeWidget.h
+
+
+ + sliderOffset + spinBox_offset + sliderGain + spinBox_gain + doubleSpinBox_integration_time + doubleSpinBox_frame_time + + + + + sliderOffset + valueChanged(int) + spinBox_offset + setValue(int) + + + 137 + 135 + + + 294 + 143 + + + + + sliderGain + valueChanged(int) + spinBox_gain + setValue(int) + + + 117 + 162 + + + 294 + 172 + + + + + spinBox_offset + valueChanged(int) + sliderOffset + setValue(int) + + + 275 + 132 + + + 154 + 136 + + + + + spinBox_gain + valueChanged(int) + sliderGain + setValue(int) + + + 268 + 163 + + + 189 + 167 + + + + +
diff --git a/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.cpp b/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.cpp new file mode 100644 index 00000000..992158dc --- /dev/null +++ b/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.cpp @@ -0,0 +1,110 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#include "dockWidgetDummyMultiChannelGrabber.h" + +//---------------------------------------------------------------------------------------------------------------------------------- +DockWidgetDummyMultiChannelGrabber::DockWidgetDummyMultiChannelGrabber(ito::AddInDataIO *grabber) : + AbstractAddInDockWidget(grabber), + m_inEditing(false), + m_firstRun(true) +{ + ui.setupUi(this); +} + +//---------------------------------------------------------------------------------------------------------------------------------- + void DockWidgetDummyMultiChannelGrabber::parametersChanged(QMap params) + { + ui.spinBpp->setValue(params["pixelFormat"].getVal()); + ui.spinWidth->setValue(params["sizex"].getVal()); + ui.spinHeight->setValue(params["sizey"].getVal()); + + if (m_firstRun) + { + ui.spinBox_gain->setDisabled( params["gain"].getFlags() & ito::ParamBase::Readonly ); + ui.horizontalSlider_gain->setDisabled( params["gain"].getFlags() & ito::ParamBase::Readonly ); + + ui.spinBox_offset->setDisabled( params["offset"].getFlags() & ito::ParamBase::Readonly ); + ui.horizontalSlider_offset->setDisabled( params["offset"].getFlags() & ito::ParamBase::Readonly ); + + ui.doubleSpinBox_integration_time->setDisabled( params["integration_time"].getFlags() & ito::ParamBase::Readonly ); + + m_firstRun = false; + } + + if (!m_inEditing) + { + m_inEditing = true; + + ui.doubleSpinBox_integration_time->setMaximum(params["integration_time"].getMax() *1000.0); + ui.doubleSpinBox_integration_time->setMinimum(params["integration_time"].getMin() *1000.0); + ui.doubleSpinBox_integration_time->setSingleStep(1); + ui.doubleSpinBox_integration_time->setValue(params["integration_time"].getVal() *1000.0); + + ui.spinBox_offset->setValue((int)(params["offset"].getVal()*100.0+0.5)); + ui.spinBox_gain->setValue((int)(params["gain"].getVal()*100.0+0.5)); + + m_inEditing = false; + } + } + +//---------------------------------------------------------------------------------------------------------------------------------- +void DockWidgetDummyMultiChannelGrabber::identifierChanged(const QString &identifier) +{ + ui.lblID->setText(identifier); +} + +//---------------------------------------------------------------------------------------------------------------------------------- +void DockWidgetDummyMultiChannelGrabber::on_spinBox_gain_valueChanged(int d) +{ + if (!m_inEditing) + { + m_inEditing = true; + QSharedPointer p(new ito::ParamBase("gain",ito::ParamBase::Double,d/100.0)); + setPluginParameter(p, msgLevelWarningAndError); + m_inEditing = false; + } +} + +//---------------------------------------------------------------------------------------------------------------------------------- +void DockWidgetDummyMultiChannelGrabber::on_spinBox_offset_valueChanged(int d) +{ + if (!m_inEditing) + { + m_inEditing = true; + QSharedPointer p(new ito::ParamBase("offset",ito::ParamBase::Double,d/100.0)); + setPluginParameter(p, msgLevelWarningAndError); + m_inEditing = false; + } +} + +//---------------------------------------------------------------------------------------------------------------------------------- +void DockWidgetDummyMultiChannelGrabber::on_doubleSpinBox_integration_time_valueChanged(double d) +{ + if (!m_inEditing) + { + m_inEditing = true; + QSharedPointer p(new ito::ParamBase("integration_time",ito::ParamBase::Double,d/1000.0)); + setPluginParameter(p, msgLevelWarningAndError); + m_inEditing = false; + } +} diff --git a/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.h b/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.h new file mode 100644 index 00000000..11452cb2 --- /dev/null +++ b/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.h @@ -0,0 +1,58 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#ifndef DOCKWIDGETDummyMultiChannelGrabber_H +#define DOCKWIDGETDummyMultiChannelGrabber_H + +#include "common/abstractAddInDockWidget.h" +#include "common/addInGrabber.h" + +#include +#include + +#include "ui_dockWidgetDummyMultiChannelGrabber.h" + +class DockWidgetDummyMultiChannelGrabber : public ito::AbstractAddInDockWidget +{ + Q_OBJECT + + public: + DockWidgetDummyMultiChannelGrabber(ito::AddInDataIO *grabber); + ~DockWidgetDummyMultiChannelGrabber() {}; + + private: + Ui::DockWidgetDummyMultiChannelGrabber ui; + bool m_inEditing; + bool m_firstRun; + + public slots: + void parametersChanged(QMap params); + void identifierChanged(const QString &identifier); + + + private slots: + void on_spinBox_offset_valueChanged(int d); + void on_spinBox_gain_valueChanged(int d); + void on_doubleSpinBox_integration_time_valueChanged(double d); +}; + +#endif diff --git a/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.ui b/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.ui new file mode 100644 index 00000000..646bfe94 --- /dev/null +++ b/DummyMultiChannelGrabber/dockWidgetDummyMultiChannelGrabber.ui @@ -0,0 +1,392 @@ + + + DockWidgetDummyMultiChannelGrabber + + + + 0 + 0 + 374 + 290 + + + + Form + + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 0 + 0 + + + + General Information + + + + 8 + + + 1 + + + 8 + + + 6 + + + + + + 0 + 0 + + + + [ID] + + + + + + + ID: + + + + + + + + + + + 0 + 0 + + + + Image Dimensions + + + + 8 + + + 1 + + + 8 + + + 8 + + + + + Width: + + + + + + + Height: + + + + + + + Bits per Pixel: + + + + + + + false + + + px + + + 1 + + + 2048 + + + 1024 + + + + + + + false + + + px + + + 1 + + + 2048 + + + 1024 + + + + + + + false + + + bits + + + 8 + + + 64 + + + 8 + + + + + + + + + + Integration + + + + 8 + + + 1 + + + 8 + + + 8 + + + + + Offset + + + + + + + 100 + + + false + + + Qt::Horizontal + + + + + + + % + + + 0 + + + 100 + + + + + + + Gain + + + + + + + 100 + + + false + + + Qt::Horizontal + + + + + + + % + + + 0 + + + 100 + + + + + + + Integrationtime + + + + + + + + + + ms + + + 1 + + + 0.000000000000000 + + + 65.000000000000000 + + + 1.000000000000000 + + + 10.000000000000000 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + spinWidth + spinHeight + spinBpp + horizontalSlider_offset + spinBox_offset + horizontalSlider_gain + spinBox_gain + doubleSpinBox_integration_time + + + + + horizontalSlider_offset + valueChanged(int) + spinBox_offset + setValue(int) + + + 130 + 204 + + + 254 + 214 + + + + + horizontalSlider_gain + valueChanged(int) + spinBox_gain + setValue(int) + + + 112 + 236 + + + 257 + 240 + + + + + spinBox_offset + valueChanged(int) + horizontalSlider_offset + setValue(int) + + + 229 + 200 + + + 161 + 207 + + + + + spinBox_gain + valueChanged(int) + horizontalSlider_gain + setValue(int) + + + 255 + 234 + + + 128 + 239 + + + + + diff --git a/DummyMultiChannelGrabber/docs/dummyMultiChannelGrabber.rst b/DummyMultiChannelGrabber/docs/dummyMultiChannelGrabber.rst new file mode 100644 index 00000000..0673adef --- /dev/null +++ b/DummyMultiChannelGrabber/docs/dummyMultiChannelGrabber.rst @@ -0,0 +1,53 @@ +=================== + DummyMultiChannelGrabber +=================== + +=============== ======================================================================================================== +**Summary**: :pluginsummary:`DummyMultiChannelGrabber` +**Type**: :plugintype:`DummyMultiChannelGrabber` +**License**: :pluginlicense:`DummyMultiChannelGrabber` +**Platforms**: Windows, Linux +**Devices**: Virtual camera providing random noise images +**Author**: :pluginauthor:`DummyMultiChannelGrabber` +=============== ======================================================================================================== + +Overview +======== + +.. pluginsummaryextended:: + :plugin: DummyMultiChannelGrabber + +Initialization +============== + +The following parameters are mandatory or optional for initializing an instance of this plugin: + + .. plugininitparams:: + :plugin: DummyMultiChannelGrabber + +Parameters +=========== + +An instance of this plugin has the following parameters: + +**binning**: {int} + Binning of different pixel, binning = x-factor * 100 + y-factor (binning in y only possible if height of sensor >= 4. +**bpp**: {int} + bitdepth of images +**frame_time**: {float} + Minimum time between the start of two consecutive acquisitions [s], default: 0.0. +**gain**: {float} + Virtual gain +**integration_time**: {float} + Minimum integration time for on acquisition [s], default: 0.0 (as fast as possible). +**name**: {str}, read-only + GrabberName +**offset**: {float} + Virtual offset +**roi**: {int rect [x0,y0,width,height]} + ROI (x,y,width,height) +**sizex**: {int}, read-only + size in x (cols) [px] +**sizey**: {int}, read-only + size in y (rows) [px] + diff --git a/DummyMultiChannelGrabber/dummyMultiChannelGrabber.cpp b/DummyMultiChannelGrabber/dummyMultiChannelGrabber.cpp new file mode 100644 index 00000000..b91ab355 --- /dev/null +++ b/DummyMultiChannelGrabber/dummyMultiChannelGrabber.cpp @@ -0,0 +1,902 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#define ITOM_IMPORT_API +#define ITOM_IMPORT_PLOTAPI + +#include "dummyMultiChannelGrabber.h" + +#ifndef WIN32 +#include +#endif + +#include + +#include "dockWidgetDummyMultiChannelGrabber.h" + +#include "gitVersion.h" +#include "pluginVersion.h" + +#ifdef WIN32 +#include +#endif + + +/*! + \class DummyMultiChannelGrabber + \brief Class for the DummyMultiChannelGrabber. The DummyMultiChannelGrabber is able to create + noisy images or simulate a typical WLI or confocal image signal. + + Usually every method in this class can be executed in an own thread. Only the constructor, + destructor, showConfDialog will be executed by the main (GUI) thread. +*/ + +//------------------------------------------------------------------------------------- +//! shows the configuration dialog. This method must be executed in the main (GUI) thread and is +//! usually called by the addIn-Manager. +/*! + creates new instance of dialogDummyMultiChannelGrabber, calls the method setVals of + dialogDummyMultiChannelGrabber, starts the execution loop and if the dialog is closed, reads the + new parameter set and deletes the dialog. + + \return retOk + \sa dialogDummyMultiChannelGrabber +*/ +const ito::RetVal DummyMultiChannelGrabber::showConfDialog(void) +{ + return apiShowConfigurationDialog(this, new DialogDummyMultiChannelGrabber(this)); +} + +//------------------------------------------------------------------------------------- +//! constructor for DummyMultiChannelGrabber +/*! + In this constructor the m_params-vector with all parameters, which are accessible by getParam or + setParam, is built. Additionally the optional docking widget for the DummyMultiChannelGrabber's + toolbar is instantiated and created by createDockWidget. + + \param [in] uniqueID is an unique identifier for this DummyMultiChannelGrabber-instance + \sa ito::tParam, createDockWidget, setParam, getParam +*/ +DummyMultiChannelGrabber::DummyMultiChannelGrabber() : + AddInMultiChannelGrabber("DummyMultiChannelGrabber") +{ + if (hasGuiSupport()) + { + // now create dock widget for this plugin + DockWidgetDummyMultiChannelGrabber* dw = new DockWidgetDummyMultiChannelGrabber(this); + Qt::DockWidgetAreas areas = Qt::AllDockWidgetAreas; + QDockWidget::DockWidgetFeatures features = QDockWidget::DockWidgetClosable | + QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable; + createDockWidget(QString(m_params["name"].getVal()), features, areas, dw); + } +} + +//------------------------------------------------------------------------------------- +//! destructor +/*! + \sa ~AddInBase +*/ +DummyMultiChannelGrabber::~DummyMultiChannelGrabber() +{ +} + +//------------------------------------------------------------------------------------- +//! init method which is called by the addInManager after the initiation of a new instance of +//! DummyMultiChannelGrabber. +/*! + This init method gets the mandatory and optional parameter vectors of type tParam and must copy + these given parameters to the internal m_params-vector. Notice that this method is called after + that this instance has been moved to its own (non-gui) thread. + + \param [in] paramsMand is a pointer to the vector of mandatory tParams. + \param [in] paramsOpt is a pointer to the vector of optional tParams. + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk +*/ +ito::RetVal DummyMultiChannelGrabber::init( + QVector* /*paramsMand*/, + QVector* paramsOpt, + ItomSharedSemaphore* waitCond) +{ + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retVal; + + // get all arguments + int sensorWidth = paramsOpt->at(0).getVal(); + int sensorHeight = paramsOpt->at(1).getVal(); + + // A multi grabber camera plugin consists of >= 1 channels. Every channel + // can have individual parameters, where a basic set of parameters are mandatory + // (like sizex, sizey, pixelFormat...). + // The channel parameters have a corresponding parameter in the m_params map + // of the overall plugin. This item in m_params is like a proxy to the underlying + // channel parameters, where the parameter 'channelSelector' defines which of + // the more than one channels is used as current proxy. + ChannelContainerMap channels; + + // create the channel parameters, that are the same for all channels + ito::Param paramSizeX("sizex", ito::ParamBase::Int | ito::ParamBase::Readonly, 16, 4096, sensorWidth, tr("sensor width of the channel").toLatin1().data()); + ito::Param paramSizeY("sizey", ito::ParamBase::Int | ito::ParamBase::Readonly, 16, 4096, sensorHeight, tr("sensor height of the channel").toLatin1().data()); + int roi[] = { 0, 0, sensorWidth, sensorHeight }; + ito::Param paramRoi("roi", ito::ParamBase::IntArray, 4, roi, tr("current region of interest of the channel (x, y, width, height)").toLatin1().data()); + + // initialize the first channel + ito::Param pixelFormat1("pixelFormat", ito::ParamBase::String, paramsOpt->at(2).getVal(), tr("pixel format of the 1st channel").toLatin1().data()); + auto pixelFormat1Meta = new ito::StringMeta(ito::StringMeta::String, "ImageFormatControl"); + pixelFormat1Meta->addItem("mono8"); + pixelFormat1Meta->addItem("mono10"); + pixelFormat1Meta->addItem("mono12"); + pixelFormat1Meta->addItem("mono16"); + pixelFormat1.setMeta(pixelFormat1Meta, true); + + ito::Param pixelFormat2("pixelFormat", ito::ParamBase::String, paramsOpt->at(3).getVal(), tr("pixel format of the 2nd channel").toLatin1().data()); + auto pixelFormat2Meta = new ito::StringMeta(ito::StringMeta::String, "ImageFormatControl"); + pixelFormat2Meta->addItem("float32"); + pixelFormat2Meta->addItem("float64"); + pixelFormat2.setMeta(pixelFormat2Meta, true); + + ito::Param pixelFormat3("pixelFormat", ito::ParamBase::String, paramsOpt->at(4).getVal(), tr("pixel format of the 3rd channel").toLatin1().data()); + auto pixelFormat3Meta = new ito::StringMeta(ito::StringMeta::String, "ImageFormatControl"); + pixelFormat3Meta->addItem("rgba8"); + pixelFormat3Meta->addItem("rgb8"); + pixelFormat3.setMeta(pixelFormat3Meta, true); + + ChannelContainer channel1(paramRoi, pixelFormat1, paramSizeX, paramSizeY); + channel1.m_channelParams["valueDescription"].setVal("intensity"); + + // every channel can also further additional parameters. + // Rules: + /* 1. If 1 or more channels have a parameter with a specific name, no + * global parameter with this name must exist. + * 2. Not every channel must have the same parameter, with the same name, + * however in initChannelsAndGlobalParameters it is verified, that + * any channel parameter is available in all channels with the same type flags. + * If a channel does not have a parameter, it is created (with default arguments) + * and the "not-available" flag. + * 3. Channel parameters of the same name must have the same type flag + * (checked in initChannelsAndGlobalParamters). + */ + channel1.addChannelParam(ito::Param( + "gammaCorrection", + ito::ParamBase::Double, 0.0, 1.0, 1.0, "gamma correction value (channelColour and channelMono only)")); + + // add channel1 to the preliminary channel map. The channel name is 'channelMono' as an example. + channels["channelMono"] = channel1; + + ChannelContainer channel2(paramRoi, pixelFormat2, paramSizeX, paramSizeY); + channel2.m_channelParams["valueDescription"].setVal("topography"); + double axisScales[] = {0.05, 0.05}; + channel2.m_channelParams["axisScales"].setVal(axisScales, 2); + ito::ByteArray axisUnits[] = { "mm", "mm" }; + channel2.m_channelParams["axisUnits"].setVal(axisUnits, 2); + + // add channel2 to the preliminary channel map. The channel name is 'channelTopo' as an example. + channels["channelTopo"] = channel2; + + ChannelContainer channel3(paramRoi, pixelFormat3, paramSizeX, paramSizeY); + channel3.m_channelParams["valueDescription"].setVal("color"); + + channel3.addChannelParam(ito::Param( + "gammaCorrection", + ito::ParamBase::Double, 0.0, 1.0, 0.8, "gamma correction value (channelColour and channelMono only)")); + + // add channel3 to the preliminary channel map. The channel name is 'channelColour' as an example. + channels["channelColour"] = channel3; + + // global parameters: + /* Other than in other plugins, global parameters, that are the same for all + channels will be added to a temporary list of Param and then given to initChannelsAndGlobalParameters. + + Internally, after some checks, they will be added to m_params, like in any other plugin. + + Due to the base class "addInMultiChannelGrabber", three default global parameters are + created and initialized: defaultChannel, channelSelector, availableChannels. + */ + + QList globalParams; + + globalParams << ito::Param( + "globalParam", + ito::ParamBase::Int, + 0, + 1, + 1, + tr("this is a global parameter").toLatin1().data()); + + ito::Param exposureTime( + "exposureTime", + ito::ParamBase::Double, + 1.e-6, + 0.5, + 10.e-3, + tr("the exposure time for all channels. This is the time that is used to acquire one frame.").toLatin1().data()); + exposureTime.getMetaT()->setRepresentation(ito::ParamMeta::Logarithmic); + globalParams << exposureTime; + + auto paramVal = ito::Param( + "demoRegexpString", + ito::ParamBase::String, + "", + tr("matches strings without whitespaces").toLatin1().data()); + paramVal.setMeta( + new ito::StringMeta(ito::StringMeta::RegExp, "^\\S+$", "DemoParameters"), true); + globalParams << paramVal; + + paramVal = ito::Param( + "demoWildcardString", + ito::ParamBase::String, + "test.bmp", + tr("dummy filename of a bmp file, pattern: *.bmp").toLatin1().data()); + paramVal.setMeta( + new ito::StringMeta(ito::StringMeta::Wildcard, "*.bmp", "DemoParameters"), true); + globalParams << paramVal; + + paramVal = ito::Param( + "demoEnumString", + ito::ParamBase::String, + "mode 1", + tr("enumeration string (mode 1, mode 2, mode 3)").toLatin1().data()); + auto sm = new ito::StringMeta(ito::StringMeta::String, "mode 1", "DemoParameters"); + sm->addItem("mode 2"); + sm->addItem("mode 3"); + paramVal.setMeta(sm, true); + globalParams << paramVal; + + paramVal = ito::Param( + "demoArbitraryString", + ito::ParamBase::String, + "any string", + tr("any string allowed").toLatin1().data()); + sm = new ito::StringMeta(ito::StringMeta::String); + sm->setCategory("DemoParameters"); + paramVal.setMeta(sm, true); + globalParams << paramVal; + + retVal += initChannelsAndGlobalParameters(channels, "channelMono", globalParams); + + if (!retVal.containsError()) + { + // check if image must be reallocated + retVal += checkDataFromAllChannels(); + + emit parametersChanged(m_params); + } + + setIdentifier(tr("Camera %1").arg(getID())); + + if (waitCond) + { + waitCond->returnValue = retVal; + waitCond->release(); + } + + setInitialized(true); // init method has been finished (independent on retval) + return retVal; +} + +//------------------------------------------------------------------------------------- +//! close method which is called before that this instance is deleted by the +//! DummyMultiChannelGrabberInterface +/*! + notice that this method is called in the actual thread of this instance. + + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk \sa ItomSharedSemaphore +*/ +ito::RetVal DummyMultiChannelGrabber::close(ItomSharedSemaphore* waitCond) +{ + ItomSharedSemaphoreLocker locker(waitCond); + + if (m_timerID > 0) + { + killTimer(m_timerID); + m_timerID = 0; + } + + if (waitCond) + { + waitCond->returnValue = ito::retOk; + waitCond->release(); + + return waitCond->returnValue; + } + else + { + return ito::retOk; + } +} + +//------------------------------------------------------------------------------------- +//! returns parameter of m_params with key name. +/*! + This method copies val of the corresponding parameter value. + + \param [in,out] val is a shared-pointer of ito::Param. + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk in case that everything is ok, else retError \sa ito::tParam, + ItomSharedSemaphore +*/ +ito::RetVal DummyMultiChannelGrabber::getParameter( + QSharedPointer val, + const ParamMapIterator& it, + const QString& key, + const QString& suffix, + int index, + bool hasIndex, + bool& ok) +{ + // just as a demo. If a specific parameter requires more actions than + // just returning its value, can be handled in this method. Else set ok to false, + // such that the returned parameter is the corresponding value in m_params and this + // is handled by AddInMultiChannelGrabber::getParam. + + if (key == "demoArbitraryString") + { + // do anything special, for instance request a current value from a hardware + // device, update the internal parameter and return this updated value. + *val = it.value(); + ok = true; + } + else + { + // let the calling method return the current value in m_params. + ok = false; + } + + return ito::retOk; +} + +//------------------------------------------------------------------------------------- +//! sets parameter of m_params with key name. +/*! + This method copies the given value to the m_params-parameter. + + \param [in] val is the ito::ParamBase value to set. + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk in case that everything is ok, else retError \sa ito::tParam, + ItomSharedSemaphore +*/ +ito::RetVal DummyMultiChannelGrabber::setParameter( + QSharedPointer& val, + const ParamMapIterator& it, + const QString& suffix, + const QString& key, + int index, + bool hasIndex, + bool& ok, + QStringList& pendingUpdate) +{ + ito::RetVal retValue; + int running = 0; // Used to check if grabber was running bevor + + // first check parameters that influence the size or data type of m_channels + //if (key == "binning") + //{ + // if (!retValue.containsError()) + // { + // if (grabberStartedCount() > 0) + // { + // running = grabberStartedCount(); + // setGrabberStarted(1); + // retValue += stopDevice(nullptr); + // } + // } + + // if (!retValue.containsError()) + // { + // int oldval = it->getVal(); + + // int ival = val->getVal(); + // int newY = ival % 100; + // int newX = (ival - newY) / 100; + + // if (m_lineCamera && (newY != 1)) + // { + // retValue += ito::RetVal( + // ito::retError, 0, "the vertical binning for a line camera must be 1"); + // } + // else if ((newX != 1 && newX != 2 && newX != 4) || (newY != 1 && newY != 2 && newY != 4)) + // { + // retValue += ito::RetVal( + // ito::retError, + // 0, + // "horizontal and vertical binning must be 1, 2 or 4 (hence vertical * 100 + " + // "horizontal)"); + // } + // else + // { + // m_totalBinning = newX * newY; + + // retValue += it->copyValueFrom(&(*val)); + + // if (oldval != ival) + // { + // int oldY = oldval % 100; + // int oldX = (oldval - oldY) / 100; + // float factorX = (float)oldX / (float)newX; + // float factorY = (float)oldY / (float)newY; + // int width, height, maxWidth, maxHeight, sizeX, sizeY, offsetX, offsetY; + // QMap::iterator i; + // for (i = m_channels.begin(); i != m_channels.end(); + // ++i) // we need to adapt the roi for each channel + // { + // width = (i.value().m_channelParams["roi"].getVal()[1] - + // i.value().m_channelParams["roi"].getVal()[0]) * + // factorX; + // height = (i.value().m_channelParams["roi"].getVal()[3] - + // i.value().m_channelParams["roi"].getVal()[2]) * + // factorY; + + // maxWidth = + // static_cast(i.value().m_channelParams["roi"].getMeta()) + // ->getWidthRangeMeta() + // .getSizeMax(); + // maxHeight = + // static_cast(i.value().m_channelParams["roi"].getMeta()) + // ->getHeightRangeMeta() + // .getSizeMax(); + + // sizeX = i.value().m_channelParams["roi"].getVal()[2] * factorX; + // sizeY = i.value().m_channelParams["roi"].getVal()[3] * factorY; + // offsetX = i.value().m_channelParams["roi"].getVal()[0] * factorX; + // offsetY = i.value().m_channelParams["roi"].getVal()[1] * factorY; + // int roi[] = {offsetX, offsetY, sizeX, sizeY}; + // i.value().m_channelParams["roi"].setVal(roi, 4); + // i.value().m_channelParams["roi"].setMeta( + // new ito::RectMeta( + // ito::RangeMeta( + // 0, width - 1, 4 / newX, 4 / newX, maxWidth * factorX, 4 / newX), + // ito::RangeMeta( + // 0, + // height - 1, + // 4 / newY, + // 4 / newY, + // maxHeight * factorY, + // 4 / newY)), + // true); + // if (i.key() == m_params["defaultChannel"].getVal()) + // { + // m_params["roi"].setVal(roi, 4); + // m_params["roi"].setMeta( + // new ito::RectMeta( + // ito::RangeMeta( + // 0, + // width - 1, + // 4 / newX, + // 4 / newX, + // maxWidth * factorX, + // 4 / newX), + // ito::RangeMeta( + // 0, + // height - 1, + // 4 / newY, + // 4 / newY, + // maxHeight * factorY, + // 4 / newY)), + // true); + // } + // } + // pendingUpdate << "roi" + // << "binning"; // add roi to update list to trigger a update of + // // sizey and sizey + // } + // } + // } + // if (running) + // { + // retValue += startDevice(NULL); + // setGrabberStarted(running); + // } + // ok = true; + //} + + //if (key == "roi") + //{ + // m_isgrabbing = false; // we need to trigger again since the roi changed + // ok = false; // we want to further process the parameter by setParam to set the size etc. + //} + + //if (key == "integration_time") + //{ + // bool timerIsRunning = m_freerunTimer.isActive(); + // m_freerunTimer.stop(); + // m_freerunTimer.setInterval( + // int((val->getVal() + m_params["frame_time"].getVal()) * 1000.0)); + // if (timerIsRunning) + // { + // m_freerunTimer.start(); + // } + // ok = false; + //} + + //if (key == "frame_time") + //{ + // bool timerIsRunning = m_freerunTimer.isActive(); + // m_freerunTimer.stop(); + // m_freerunTimer.setInterval( + // int((val->getVal() + m_params["integration_time"].getVal()) * 1000.0)); + // if (timerIsRunning) + // { + // m_freerunTimer.start(); + // } + // ok = false; + //} + //else + //{ + // ok = false; // set ok to false to let setParam process the parameter + // + //} + + ok = false; // set ok to false to let setParam process the parameter + + sendDataToListeners(0); + + return retValue; +} + +//------------------------------------------------------------------------------------- +ito::RetVal DummyMultiChannelGrabber::retrieveData(const QStringList& channels /*= QStringList()*/) +{ + ito::RetVal retVal; + + return retVal; +} + +//------------------------------------------------------------------------------------- +QRect roiParamToRect(const ito::ParamBase& roiParam) +{ + const int* roi = roiParam.getVal(); + // int roi[] = { 0, 0, sensorWidth, sensorHeight }; + + QRect r(roi[0], roi[1], roi[2], roi[3]); + return r; +} + +//------------------------------------------------------------------------------------- +//! With startDevice this camera is initialized. +/*! + In the DummyMultiChannelGrabber, this method does nothing. In general, the hardware camera + should be intialized in this method and necessary memory should be allocated. + + \note This method is similar to VideoCapture::open() of openCV + + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk if starting was successfull, retWarning if startDevice has been calling + at least twice. +*/ +ito::RetVal DummyMultiChannelGrabber::startDevice(ItomSharedSemaphore* waitCond) +{ + ItomSharedSemaphoreLocker locker(waitCond); + + ito::RetVal retValue; + + incGrabberStarted(); + + if (grabberStartedCount() == 1) + { + // the grabber is started for the first time + retValue += checkData(); + + if (retValue == ito::retOk) + { + // configure emulator for mono image + QByteArray pixelFormatMono = m_channels["channelMono"].m_channelParams["pixelFormat"].getVal(); + QRect roiMono = roiParamToRect(m_channels["channelMono"].m_channelParams["roi"]); + m_camEmulator.configureImageMono(roiMono, pixelFormatMono.mid(4 /*mono*/).toInt()); + + // configure emulator for topography image (here: float) + QByteArray pixelFormatTopo = m_channels["channelTopo"].m_channelParams["pixelFormat"].getVal(); + QRect roiTopo = roiParamToRect(m_channels["channelTopo"].m_channelParams["roi"]); + m_camEmulator.configureImageTopography(roiTopo, pixelFormatTopo.mid(5 /*float*/).toInt() == 32); + + // configure emulator for colour image + QByteArray pixelFormatColour = m_channels["channelColour"].m_channelParams["pixelFormat"].getVal(); + QRect roiColour = roiParamToRect(m_channels["channelColour"].m_channelParams["roi"]); + m_camEmulator.configureImageColor(roiColour, pixelFormatColour == "rgba32"); + } + } + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + + return retValue; +} + +//------------------------------------------------------------------------------------- +//! With stopDevice the camera device is stopped (opposite to startDevice) +/*! + In this DummyMultiChannelGrabber, this method does nothing. In general, the hardware camera + should be closed in this method. + + \note This method is similar to VideoCapture::release() of openCV + + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk if everything is ok, retError if camera wasn't started before \sa + startDevice +*/ +ito::RetVal DummyMultiChannelGrabber::stopDevice(ItomSharedSemaphore* waitCond) +{ + ItomSharedSemaphoreLocker locker(waitCond); + ito::RetVal retValue = ito::retOk; + + decGrabberStarted(); + + if (grabberStartedCount() < 0) + { + retValue += ito::RetVal( + ito::retWarning, + 1001, + tr("stopDevice of DummyMultiChannelGrabber can not be executed, since camera has not " + "been started.") + .toLatin1() + .data()); + setGrabberStarted(0); + } + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + + return retValue; +} + + +//------------------------------------------------------------------------------------- +//! Call this method to trigger a new image. +/*! + By this method a new image is trigger by the camera, that means the acquisition of the image + starts in the moment, this method is called. The new image is then stored either in internal + camera memory or in internal memory of this class. + + \note This method is similar to VideoCapture::grab() of openCV + + \param [in] trigger may describe the trigger parameter (unused here) + \param [in] waitCond is the semaphore (default: NULL), which is released if this method has been + terminated \return retOk if everything is ok, retError if camera has not been started or an older + image lies in memory which has not be fetched by getVal, yet. \sa getVal +*/ +ito::RetVal DummyMultiChannelGrabber::acquire(const int /*trigger*/, ItomSharedSemaphore* waitCond) +{ + ito::RetVal retValue = ito::retOk; + ItomSharedSemaphoreLocker locker(waitCond); + + double exposureTimeS = m_params["exposureTime"].getVal(); + + if (waitCond) + { + waitCond->returnValue = retValue; + waitCond->release(); + } + + // the emulator + if (m_camEmulator.grabImages(true, true, true, exposureTimeS * 1000.0)) + { + m_camEmulator.imageMono().deepCopyPartial(m_channels["channelMono"].m_data); + m_camEmulator.imageTopography().deepCopyPartial(m_channels["channelTopo"].m_data); + m_camEmulator.imageColor().deepCopyPartial(m_channels["channelColour"].m_data); + } + else + { + // todo + } + + + return retValue; +} + +////------------------------------------------------------------------------------------- +////! Returns the grabbed camera frame as a shallow copy. +///*! +// This method copies the recently grabbed camera frame to the given DataObject-handle +// +// \note This method is similar to VideoCapture::retrieve() of openCV +// +// \param [in,out] vpdObj is the pointer to a given dataObject (this pointer should be cast to +// ito::DataObject*) where the acquired image is shallow-copied to. \param [in] waitCond is the +// semaphore (default: NULL), which is released if this method has been terminated \return retOk if +// everything is ok, retError is camera has not been started or no image has been acquired by the +// method acquire. \sa DataObject, acquire +//*/ +//ito::RetVal DummyMultiChannelGrabber::getVal(void* vpdObj, ItomSharedSemaphore* waitCond) +//{ +// ItomSharedSemaphoreLocker locker(waitCond); +// ito::RetVal retValue(ito::retOk); +// ito::DataObject* dObj = reinterpret_cast(vpdObj); +// +// if (!dObj) +// { +// retValue += ito::RetVal( +// ito::retError, 0, tr("Empty dataObject handle retrieved from caller").toLatin1().data()); +// } +// +// if (!retValue.containsError()) +// { +// retValue += retrieveData(); +// } +// +// if (!retValue.containsError()) +// { +// // don't wait for live image, since user should get the image as fast as possible. +// sendDataToListeners(0); +// +// (*dObj) = m_channels[m_params["defaultChannel"].getVal()].m_data; +// } +// +// if (waitCond) +// { +// waitCond->returnValue = retValue; +// waitCond->release(); +// } +// +// return retValue; +//} +// +////------------------------------------------------------------------------------------- +////! Returns the grabbed camera frame as a deep copy. +///*! +// This method copies the recently grabbed camera frame to the given DataObject. Therefore this +// camera size must fit to the data structure of the DataObject. +// +// \note This method is similar to VideoCapture::retrieve() of openCV +// +// \param [in,out] vpdObj is the pointer to a given dataObject (this pointer should be cast to +// ito::DataObject*) where the acquired image is deep copied to. \param [in] waitCond is the +// semaphore (default: NULL), which is released if this method has been terminated \return retOk if +// everything is ok, retError is camera has not been started or no image has been acquired by the +// method acquire. \sa DataObject, acquire +//*/ +//ito::RetVal DummyMultiChannelGrabber::copyVal(void* vpdObj, ItomSharedSemaphore* waitCond) +//{ +// ItomSharedSemaphoreLocker locker(waitCond); +// ito::RetVal retValue(ito::retOk); +// ito::DataObject* dObj = reinterpret_cast(vpdObj); +// +// if (!dObj) +// { +// retValue += ito::RetVal( +// ito::retError, 0, tr("Empty dataObject handle retrieved from caller").toLatin1().data()); +// } +// else +// { +// retValue += checkData(dObj); +// } +// +// if (!retValue.containsError()) +// { +// retValue += retrieveData(dObj); +// } +// +// if (!retValue.containsError()) +// { +// don't wait for live image, since user should get the image as fast as possible. +// sendDataToListeners(0); +// } +// +// if (waitCond) +// { +// waitCond->returnValue = retValue; +// waitCond->release(); +// } +// +// return retValue; +//} + + +//------------------------------------------------------------------------------------- +ito::Rgba32 hsv2rgb(float hue, float saturation, float intensity, ito::uint8 alpha) +{ + double hh, p, q, t, ff; + long i; + ito::Rgba32 out; + + out.a = alpha; + + if (saturation <= 0.0) + { + // < is bogus, just shuts up warnings + out.r = intensity * 255; + out.g = out.b = out.r; + return out; + } + + hh = hue * 360; + + if (hh >= 360.0) + { + hh = 0.0; + } + + hh /= 60.0; + + i = (long)hh; + ff = hh - i; + p = intensity * (1.0 - saturation); + q = intensity * (1.0 - (saturation * ff)); + t = intensity * (1.0 - (saturation * (1.0 - ff))); + + switch (i) { + case 0: + out.r = intensity; + out.g = t; + out.b = p; + break; + case 1: + out.r = q; + out.g = intensity; + out.b = p; + break; + case 2: + out.r = p; + out.g = intensity; + out.b = t; + break; + + case 3: + out.r = p; + out.g = q; + out.b = intensity; + break; + case 4: + out.r = t; + out.g = p; + out.b = intensity; + break; + case 5: + default: + out.r = intensity; + out.g = p; + out.b = q; + break; + } + return out; +} + +//------------------------------------------------------------------------------------- +void DummyMultiChannelGrabber::dockWidgetVisibilityChanged(bool visible) +{ + if (getDockWidget()) + { + QWidget* widget = getDockWidget()->widget(); + if (visible) + { + connect( + this, + SIGNAL(parametersChanged(QMap)), + widget, + SLOT(parametersChanged(QMap))); + emit parametersChanged(m_params); + } + else + { + disconnect( + this, + SIGNAL(parametersChanged(QMap)), + widget, + SLOT(parametersChanged(QMap))); + } + } +} diff --git a/DummyMultiChannelGrabber/dummyMultiChannelGrabber.h b/DummyMultiChannelGrabber/dummyMultiChannelGrabber.h new file mode 100644 index 00000000..36564ff9 --- /dev/null +++ b/DummyMultiChannelGrabber/dummyMultiChannelGrabber.h @@ -0,0 +1,89 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#pragma once + +#include "common/addInMultiChannelGrabber.h" +#include "common/typeDefs.h" +#include "dialogDummyMultiChannelGrabber.h" +#include "cameraEmulator.h" + +#include +#include + + +//------------------------------------------------------------------------------------- +class DummyMultiChannelGrabber : public ito::AddInMultiChannelGrabber +{ + Q_OBJECT + +protected: + ~DummyMultiChannelGrabber(); + DummyMultiChannelGrabber(); + + ito::RetVal getParameter( + QSharedPointer val, + const ParamMapIterator& it, + const QString& key, + const QString& suffix, + int index, + bool hasIndex, + bool& ok); + + ito::RetVal setParameter( + QSharedPointer& val, + const ParamMapIterator& it, + const QString& suffix, + const QString& key, + int index, + bool hasIndex, + bool& ok, + QStringList& pendingUpdate); + + ito::RetVal retrieveData(const QStringList& channels = QStringList()); + +public: + friend class DummyMultiChannelGrabberInterface; + + const ito::RetVal showConfDialog(void); + + //!< indicates that this plugin has got a configuration dialog + int hasConfDialog(void) { return 1; }; + +private: + CameraEmulator m_camEmulator; + +signals: + +public slots: + + ito::RetVal init(QVector* paramsMand, QVector* paramsOpt, ItomSharedSemaphore* waitCond = nullptr); + ito::RetVal close(ItomSharedSemaphore* waitCond); + + ito::RetVal startDevice(ItomSharedSemaphore* waitCond); + ito::RetVal stopDevice(ItomSharedSemaphore* waitCond); + ito::RetVal acquire(const int trigger, ItomSharedSemaphore* waitCond = nullptr); + + +private slots: + void dockWidgetVisibilityChanged(bool visible); +}; diff --git a/DummyMultiChannelGrabber/dummyMultiChannelGrabberInterface.cpp b/DummyMultiChannelGrabber/dummyMultiChannelGrabberInterface.cpp new file mode 100644 index 00000000..e2192daf --- /dev/null +++ b/DummyMultiChannelGrabber/dummyMultiChannelGrabberInterface.cpp @@ -0,0 +1,182 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#include "dummyMultiChannelGrabberInterface.h" + +#include + +#include "gitVersion.h" +#include "pluginVersion.h" +#include "dummyMultiChannelGrabber.h" + + +//------------------------------------------------------------------------------------- +/*! + \class DummyMultiChannelGrabberInterface + \brief Small interface class for class DummyMultiChannelGrabber. This class contains basic + information about DummyMultiChannelGrabber as is able to create one or more new instances of + DummyMultiChannelGrabber. +*/ + +//------------------------------------------------------------------------------------- +//! creates new instance of DummyMultiChannelGrabber and returns the instance-pointer. +/*! + \param [in,out] addInInst is a double pointer of type ito::AddInBase. The newly created + DummyMultiChannelGrabber-instance is stored in *addInInst \return retOk \sa + DummyMultiChannelGrabber +*/ +ito::RetVal DummyMultiChannelGrabberInterface::getAddInInst(ito::AddInBase** addInInst) +{ + NEW_PLUGININSTANCE(DummyMultiChannelGrabber) + return ito::retOk; +} + +//------------------------------------------------------------------------------------- +//! deletes instance of DummyMultiChannelGrabber. This instance is given by parameter addInInst. +/*! + \param [in] double pointer to the instance which should be deleted. + \return retOk + \sa DummyMultiChannelGrabber +*/ +ito::RetVal DummyMultiChannelGrabberInterface::closeThisInst(ito::AddInBase** addInInst) +{ + REMOVE_PLUGININSTANCE(DummyMultiChannelGrabber) + return ito::retOk; +} + +//------------------------------------------------------------------------------------- +//! constructor for interace +/*! + defines the plugin type (dataIO and grabber) and sets the plugins object name. If the real + plugin (here: DummyMultiChannelGrabber) should or must be initialized (e.g. by a Python call) + with mandatory or optional parameters, please initialize both vectors m_initParamsMand and + m_initParamsOpt within this constructor. +*/ +DummyMultiChannelGrabberInterface::DummyMultiChannelGrabberInterface() +{ + m_autoLoadPolicy = ito::autoLoadKeywordDefined; + m_autoSavePolicy = ito::autoSaveAlways; + + m_type = ito::typeDataIO | ito::typeGrabber; + setObjectName("DummyMultiChannelGrabber"); + + // for the docstring, please don't set any spaces at the beginning of the line. + /* char docstring[] = \ + "The DummyMultiChannelGrabber is a virtual camera which emulates a camera with white noise. \n\ + \n\ + The camera is initialized with a maximum width and height of the simulated camera chip (both + need to be a multiple + of 4). \ + The noise is always scaled in the range between 0 and the current bitdepth (bpp - bit per + pixel). The real size of + the camera \ + image is controlled using the parameter 'roi' if the sizes stay within the limits given by the + size of the camera + chip.\n\ + \n\ + You can initialize this camera either as a 2D sensor with a width and height >= 4 or as line + camera whose height is + equal to 1. \n\ + \n\ + This plugin can also be used as template for other grabber.";*/ + + m_description = QObject::tr("A virtual white noise grabber"); + // m_detaildescription = QObject::tr(docstring); + m_detaildescription = QObject::tr( + "The DummyMultiChannelGrabber is a virtual camera which emulates a camera with multiple channels with white noise. \n\ +\n\ +The camera is initialized with a maximum width and height of the simulated camera chip (both need to be a multiple of 4). \ +The noise is always scaled in the range between 0 and the current bitdepth (bpp - bit per pixel). The real size of the camera \ +image is controlled using the parameter 'roi' if the sizes stay within the limits given by the size of the camera chip.\n\ +\n\ +You can initialize this camera either as a 2D sensor with a width and height >= 4 or as line camera whose height is equal to 1. \n\ +\n\ +This plugin can also be used as template for other grabbers."); + + m_author = "R. Hahn, ITO, University Stuttgart"; + m_version = (PLUGIN_VERSION_MAJOR << 16) + (PLUGIN_VERSION_MINOR << 8) + PLUGIN_VERSION_PATCH; + m_minItomVer = CREATEVERSION(1, 4, 0); + m_maxItomVer = MAXVERSION; + m_license = QObject::tr("Licensed under LPGL."); + m_aboutThis = tr(GITVERSION); + + m_initParamsMand.clear(); + + ito::Param param( + "sensorWidth", + ito::ParamBase::Int, + 640, + new ito::IntMeta(4, 4096, 4), + tr("Width of sensor chip. In this demo, the width of the sensor is the same for " + "all channels (could be different, if implemented).").toLatin1().data()); + m_initParamsOpt.append(param); + + param = ito::Param( + "sensorHeight", + ito::ParamBase::Int, + 480, + new ito::IntMeta(1, 4096, 1), + tr("Height of sensor chip. In this demo, the height is the same for all " + "channels. However, it could also be different, if implemented.").toLatin1().data()); + m_initParamsOpt.append(param); + + param = ito::Param( + "pixelFormatChannel1", + ito::ParamBase::String, + "mono8", + tr("Pixel format for the 1st channel (here: a grayscale intensity image).").toLatin1().data()); + ito::StringMeta* m = new ito::StringMeta(ito::StringMeta::String, "mono8"); + m->addItem("mono10"); + m->addItem("mono12"); + m->addItem("mono16"); + param.setMeta(m, true); + m_initParamsOpt.append(param); + + param = ito::Param( + "pixelFormatChannel2", + ito::ParamBase::String, + "float32", + tr("Pixel format for the 2nd channel (here: a float32 or float64 disparity image).").toLatin1().data()); + m = new ito::StringMeta(ito::StringMeta::String, "float32"); + m->addItem("float64"); + param.setMeta(m, true); + m_initParamsOpt.append(param); + + param = ito::Param( + "pixelFormatChannel3", + ito::ParamBase::String, + "rgba8", + tr("Pixel format for the 3nd channel (here: color image with or without alpha channel).").toLatin1().data()); + m = new ito::StringMeta(ito::StringMeta::String, "rgba8"); + m->addItem("rgb8"); + param.setMeta(m, true); + m_initParamsOpt.append(param); +} + +//------------------------------------------------------------------------------------- +//! destructor +/*! + +*/ +DummyMultiChannelGrabberInterface::~DummyMultiChannelGrabberInterface() +{ +} diff --git a/DummyMultiChannelGrabber/dummyMultiChannelGrabberInterface.h b/DummyMultiChannelGrabber/dummyMultiChannelGrabberInterface.h new file mode 100644 index 00000000..c83f1cf4 --- /dev/null +++ b/DummyMultiChannelGrabber/dummyMultiChannelGrabberInterface.h @@ -0,0 +1,58 @@ +/* ******************************************************************** + Plugin "DummyMultiChannelGrabber" for itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of a plugin for the measurement software itom. + + This itom-plugin is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + itom and its plugins are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#pragma once + +#include "common/addInMultiChannelGrabber.h" +#include "common/typeDefs.h" + +#include +#include + +//------------------------------------------------------------------------------------- +class DummyMultiChannelGrabberInterface : public ito::AddInInterfaceBase +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "ito.AddInInterfaceBase") + + /*!< this DummyMultiChannelGrabberInterface implements the + ito::AddInInterfaceBase-interface, which makes it available as plugin in itom */ + Q_INTERFACES(ito::AddInInterfaceBase) + + PLUGIN_ITOM_API + +public: + /*!< Constructor */ + DummyMultiChannelGrabberInterface(); + + /*!< Destructor */ + ~DummyMultiChannelGrabberInterface(); + + /*!< creates new instance of DummyMultiChannelGrabber and returns this instance */ + ito::RetVal getAddInInst(ito::AddInBase** addInInst); + +private: + + /*!< closes any specific instance of DummyMultiChannelGrabber, given by *addInInst */ + ito::RetVal closeThisInst(ito::AddInBase** addInInst); + +}; diff --git a/DummyMultiChannelGrabber/pluginVersion.h b/DummyMultiChannelGrabber/pluginVersion.h new file mode 100644 index 00000000..18cabac3 --- /dev/null +++ b/DummyMultiChannelGrabber/pluginVersion.h @@ -0,0 +1,45 @@ +/* ******************************************************************** + itom software + URL: http://www.uni-stuttgart.de/ito + Copyright (C) 2023, Institut fuer Technische Optik (ITO), + Universitaet Stuttgart, Germany + + This file is part of itom and its software development toolkit (SDK). + + itom is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public Licence as published by + the Free Software Foundation; either version 2 of the Licence, or (at + your option) any later version. + + In addition, as a special exception, the Institut fuer Technische + Optik (ITO) gives you certain additional rights. + These rights are described in the ITO LGPL Exception version 1.0, + which can be found in the file LGPL_EXCEPTION.txt in this package. + + itom is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library + General Public Licence for more details. + + You should have received a copy of the GNU Library General Public License + along with itom. If not, see . +*********************************************************************** */ + +#ifndef PLUGINVERSION_H +#define PLUGINVERSION_H + +#include "itom_sdk.h" + +#define PLUGIN_VERSION_MAJOR 1 +#define PLUGIN_VERSION_MINOR 5 +#define PLUGIN_VERSION_PATCH 0 +#define PLUGIN_VERSION_REVISION 0 +#define PLUGIN_VERSION CREATE_VERSION(PLUGIN_VERSION_MAJOR,PLUGIN_VERSION_MINOR,PLUGIN_VERSION_PATCH) +#define PLUGIN_VERSION_STRING CREATE_VERSION_STRING(PLUGIN_VERSION_MAJOR,PLUGIN_VERSION_MINOR,PLUGIN_VERSION_PATCH) +#define PLUGIN_COMPANY "Institut fuer Technische Optik, University Stuttgart" +#define PLUGIN_COPYRIGHT "(C) 2023, ITO, University Stuttgart" +#define PLUGIN_NAME "DummyMultiChannelGrabber" + +//---------------------------------------------------------------------------------------------------------------------------------- + +#endif // PLUGINVERSION_H diff --git a/DummyMultiChannelGrabber/translation/DummyMultiChannelGrabber_de.ts b/DummyMultiChannelGrabber/translation/DummyMultiChannelGrabber_de.ts new file mode 100644 index 00000000..3c69befd --- /dev/null +++ b/DummyMultiChannelGrabber/translation/DummyMultiChannelGrabber_de.ts @@ -0,0 +1,4 @@ + + + +