4#include "moc_ImageViewer.cpp"
5#include "ui_ImageViewer.h"
11 : QModuleWidget(Owner, parent),
13 HistogramContextMenu(new QMenu(this)), HistogramLinLogActionGroup(new QActionGroup(this)),
14 HistogramGraph(nullptr),
15 GraphicsView(nullptr), GraphicsPixmapItem(nullptr), GraphicsScene(new QGraphicsScene(this))
19 ui->action_Zoom_fit->setChecked(
true);
35 connect(
ui->Histogram, &QQuickWidget::statusChanged, [
this](QQuickWidget::Status Status) {
36 if (Status == QQuickWidget::Status::Ready && ui->Histogram->rootObject())
38 auto BackendVariant = ui->Histogram->rootObject()->property(
"backend");
39 HistogramGraph = BackendVariant.isValid() ? BackendVariant.value<DynExpQuick::DynExpLineGraphBackend*>() : nullptr;
43 HistogramGraph->InsertSeries(
"I", QColorConstants::White);
44 HistogramGraph->InsertSeries(
"R", QColorConstants::Red);
45 HistogramGraph->InsertSeries(
"G", QColorConstants::Green);
46 HistogramGraph->InsertSeries(
"B", QColorConstants::Blue);
50 ui->Histogram->loadFromModule(
"Modules.DynExpQuick",
"QDynExpLineGraph");
52 HistogramPlotInfo.XLabel =
"pixel value";
55 GraphicsView->setObjectName(QString::fromUtf8(
"Image"));
56 QSizePolicy ImageSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
57 ImageSizePolicy.setHorizontalStretch(1);
58 ImageSizePolicy.setVerticalStretch(0);
59 ImageSizePolicy.setHeightForWidth(GraphicsView->sizePolicy().hasHeightForWidth());
60 GraphicsView->setSizePolicy(ImageSizePolicy);
61 GraphicsView->setMinimumSize(QSize(400, 300));
62 GraphicsView->viewport()->setProperty(
"cursor", QVariant(QCursor(Qt::CrossCursor)));
63 GraphicsView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
65 GraphicsPixmapItem = GraphicsScene->addPixmap(Pixmap);
66 GraphicsView->setScene(GraphicsScene);
67 GraphicsView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
68 GraphicsView->viewport()->installEventFilter(
this);
69 GraphicsView->viewport()->setMouseTracking(
true);
72 void ImageViewerWidget::SetImage(
const QImage& NewImage)
noexcept
74 Pixmap = QPixmap::fromImage(NewImage);
78 void ImageViewerWidget::SetImageViewEnabled(
bool Enable)
81 GraphicsView->setEnabled(Enable);
86 IntensityHistogram = std::move(NewIntensityHistogram);
91 RGBHistogram = std::move(NewRGBHistogram);
94 auto ImageViewerWidget::GetComputeHistogram() const noexcept
98 if (!ui->ExposureTimeGroupBox->isVisible() || ui->ExposureTimeGroupBox->visibleRegion().isEmpty())
99 return CHT::NoHistogram;
101 if (HistogramBWAction->isChecked())
102 return HistogramColorAction->isChecked() ? CHT::IntensityAndRGBHistogram : CHT::IntensityHistogram;
103 if (HistogramColorAction->isChecked())
104 return CHT::RGBHistogram;
106 return CHT::NoHistogram;
109 void ImageViewerWidget::UpdateScene()
111 if (GraphicsView->isVisible() && !GraphicsView->visibleRegion().isEmpty() && !Pixmap.isNull())
113 GraphicsPixmapItem->setPixmap(Pixmap);
114 GraphicsScene->update();
116 OnZoomFitClicked(ui->action_Zoom_fit->isChecked());
119 ui->ImageGeometry->setText(QString::number(Pixmap.width()) +
" x " + QString::number(Pixmap.height()));
122 void ImageViewerWidget::UpdateHistogram()
124 if (ui->ExposureTimeGroupBox->isVisible() && !ui->ExposureTimeGroupBox->visibleRegion().isEmpty())
125 UpdateHistogramImpl();
128 bool ImageViewerWidget::eventFilter(QObject* obj, QEvent* event)
130 if (GraphicsView->viewport())
131 if (event->type() == QEvent::MouseMove)
133 OnImageMouseMove(
static_cast<QMouseEvent*
>(event));
138 return QObject::eventFilter(obj, event);
141 void ImageViewerWidget::resizeEvent(QResizeEvent* event)
143 OnZoomFitClicked(ui->action_Zoom_fit->isChecked());
146 void ImageViewerWidget::UpdateHistogramImpl()
149 auto ComputeHistogram = GetComputeHistogram();
151 bool LogPlot = HistogramLogAction->isChecked();
152 QList<QPointF> SeriesI, SeriesR, SeriesG, SeriesB;
153 for (
int i = 0; i < static_cast<int>(IntensityHistogram.size()); ++i)
155 if (ComputeHistogram == CHT::IntensityHistogram ||
156 ComputeHistogram == CHT::IntensityAndRGBHistogram)
159 SeriesI << QPointF(i, (LogPlot ? std::log10(IntensityHistogram[i] + .1) : IntensityHistogram[i]));
162 if (ComputeHistogram == CHT::RGBHistogram ||
163 ComputeHistogram == CHT::IntensityAndRGBHistogram)
166 SeriesR << QPointF(i, (LogPlot ? std::log10(std::get<0>(RGBHistogram)[i] + .1) : std::get<0>(RGBHistogram)[i]));
167 SeriesG << QPointF(i, (LogPlot ? std::log10(std::get<1>(RGBHistogram)[i] + .1) : std::get<1>(RGBHistogram)[i]));
168 SeriesB << QPointF(i, (LogPlot ? std::log10(std::get<2>(RGBHistogram)[i] + .1) : std::get<2>(RGBHistogram)[i]));
172 HistogramPlotInfo.Reset();
173 ProcessedSeriesI.clear();
174 ProcessedSeriesR.clear();
175 ProcessedSeriesG.clear();
176 ProcessedSeriesB.clear();
177 if (ComputeHistogram == CHT::IntensityHistogram ||
178 ComputeHistogram == CHT::IntensityAndRGBHistogram)
180 HistogramPlotInfo.ProcessSamples(SeriesI, ProcessedSeriesI, 0);
183 if (ComputeHistogram == CHT::RGBHistogram ||
184 ComputeHistogram == CHT::IntensityAndRGBHistogram)
186 HistogramPlotInfo.ProcessSamples(SeriesR, ProcessedSeriesR, 1);
187 HistogramPlotInfo.ProcessSamples(SeriesG, ProcessedSeriesG, 2);
188 HistogramPlotInfo.ProcessSamples(SeriesB, ProcessedSeriesB, 3);
192 HistogramPlotInfo.YLabel = QString(LogPlot ?
"log. " :
"") +
"counts";
193 HistogramPlotInfo.AdjustAxesLimits();
195 HistogramGraph->UpdateSeries(0, ProcessedSeriesI, HistogramPlotInfo);
196 HistogramGraph->UpdateSeries(1, ProcessedSeriesR, HistogramPlotInfo);
197 HistogramGraph->UpdateSeries(2, ProcessedSeriesG, HistogramPlotInfo);
198 HistogramGraph->UpdateSeries(3, ProcessedSeriesB, HistogramPlotInfo);
199 HistogramGraph->UpdateData(HistogramPlotInfo);
202 void ImageViewerWidget::OnHistogramContextMenuRequested(
const QPoint& Position)
204 HistogramContextMenu->exec(ui->Histogram->mapToGlobal(Position));
207 void ImageViewerWidget::OnSaveImageClicked()
210 if (Filename.isEmpty())
213 SaveImageFilename = Filename;
216 void ImageViewerWidget::OnZoomResetClicked()
218 ui->action_Zoom_fit->setChecked(
false);
219 GraphicsView->ZoomReset();
222 void ImageViewerWidget::OnZoomInClicked()
224 ui->action_Zoom_fit->setChecked(
false);
225 GraphicsView->ZoomIn();
228 void ImageViewerWidget::OnZoomOutClicked()
230 ui->action_Zoom_fit->setChecked(
false);
231 GraphicsView->ZoomOut();
234 void ImageViewerWidget::OnZoomFitClicked(
bool Checked)
237 GraphicsView->fitInView(GraphicsPixmapItem, Qt::AspectRatioMode::KeepAspectRatio);
240 void ImageViewerWidget::OnImageMouseMove(QMouseEvent* Event)
242 auto LocalPoint = GraphicsView->mapFromGlobal(Event->globalPosition().toPoint());
244 if (!GraphicsView->items(LocalPoint).empty())
246 auto Point = GraphicsView->mapToScene(LocalPoint).toPoint();
248 ui->CursorPosition->setText(
"X:" + QString::number(Point.x()) +
", Y:" + QString::number(Point.y()));
262 double ImageViewerData::CalcBrennerGradientFromImage()
const
264 if (CurrentImage.isNull())
265 return std::numeric_limits<double>::quiet_NaN();
267 const auto GrayImage = CurrentImage.convertToFormat(QImage::Format::Format_Grayscale8);
268 auto RawImage = GrayImage.constBits();
270 double BrennerGradient = .0;
271 for (
int y = 0; y < GrayImage.height(); ++y)
273 for (
int x = 0; x < GrayImage.width() - 2; ++x)
275 BrennerGradient += std::pow((
static_cast<double>(*RawImage) -
static_cast<double>(*(RawImage + 2))) / 255.0, 2);
284 return BrennerGradient / GrayImage.width() / GrayImage.height() * 1e3;
287 void ImageViewerData::Init()
289 UIInitialized =
false;
298 AutoSaveFilename.clear();
300 CurrentImage = QImage();
301 HasImageChanged =
false;
302 ImageCapturingPaused =
false;
303 CaptureAfterPause =
false;
305 IntensityHistogram = {};
310 : QModuleBase(OwnerThreadID, std::move(Params)),
311 StateMachine(ReadyState,
312 AutofocusInitState, AutofocusGotoSampleState, AutofocusWaitBeforeCaptureState,
313 AutofocusWaitForImageState, AutofocusStepState, AutofocusFinishedState),
314 PauseUpdatingUI(std::make_shared<std::atomic<bool>>(false))
330 if (!Image.save(Filename))
367 auto Widget = std::make_unique<ImageViewerWidget>(*
this);
385 auto Widget = GetWidget<ImageViewerWidget>();
386 auto ModuleData = DynExp::dynamic_ModuleData_cast<ImageViewer>(ModuleDataGetter());
397 Widget->ui->CameraModeGroupBox->setVisible(
false);
400 for (
const auto& Mode :
ModuleData->CameraModes)
402 Widget->ui->CBCameraMode->insertItem(
Widget->ui->CBCameraMode->count(), QString::fromStdString(Mode));
403 Widget->ui->CBCameraMode->setItemData(
Widget->ui->CBCameraMode->count() - 1, QString::fromStdString(Mode), Qt::ToolTipRole);
407 Widget->ui->CBCameraMode->setCurrentIndex(0);
414 Widget->ui->action_Capture_Frame->setEnabled(
Ready);
415 Widget->ui->action_Capture_continuously->setEnabled(
Ready);
417 Widget->ui->ImageModifiersGroupBox->setEnabled(
Ready);
422 Widget->ui->ExposureTimeMinValue->setText(
"min. " + QString::number(
ModuleData->MinExposureTime.count()) +
" ms");
423 Widget->ui->ExposureTimeMaxValue->setText(
"max. " + QString::number(
ModuleData->MaxExposureTime.count()) +
" ms");
427 if (!
Widget->ui->ExposureTime->hasFocus())
429 const QSignalBlocker Blocker(
Widget->ui->ExposureTime);
430 Widget->ui->ExposureTime->setValue(Util::NumToT<int>(
ModuleData->CurrentExposureTime.count()));
433 if (!Autofocusing && !
ModuleData->ImageCapturingPaused)
436 if (
Widget->ui->ImageModifiersGroupBox->isChecked())
440 ImageTransformation.
ContrastFactor = std::pow(10,
Widget->ui->ImageModifiersContrast->value() / 10.f);
445 auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(
ModuleData->Camera->GetInstrumentData());
446 CameraData->SetImageTransformation(ImageTransformation);
458 if (
ModuleData->ComputeHistogram == CHT::IntensityHistogram ||
459 ModuleData->ComputeHistogram == CHT::IntensityAndRGBHistogram)
461 if (
ModuleData->ComputeHistogram == CHT::RGBHistogram ||
462 ModuleData->ComputeHistogram == CHT::IntensityAndRGBHistogram)
468 Widget->UpdateHistogram();
470 if (
Ready && !
Widget->GetSaveImageFilename().isEmpty())
475 Widget->ResetSaveImageFilename();
479 Widget->ui->action_Autofocus->setChecked(Autofocusing);
482 Widget->ui->CurrentFPS->setText(
"Autofocusing...");
484 Widget->ui->CurrentFPS->setText(
"Capturing frame...");
488 Widget->ui->CurrentFPS->setText(
"Capturing... (FPS: " + QString::number(
ModuleData->CurrentFPS,
'f', 1) +
489 +
", Brenner gradient: " + QString::number(
ModuleData->CalcBrennerGradientFromImage(),
'f', 3) +
")");
491 Widget->ui->CurrentFPS->setText(
"Capturing... (FPS: " + QString::number(
ModuleData->CurrentFPS,
'f', 1) +
")");
495 Widget->ui->CurrentFPS->setText(
"Stopped");
500 const auto CurrentState =
StateMachine.GetCurrentState()->GetState();
507 const auto CurrentState =
StateMachine.GetCurrentState()->GetState();
520 ModuleData->Communicator->PostEvent(*
this, Event);
535 auto ModuleParams = DynExp::dynamic_Params_cast<ImageViewer>(Instance->
ParamsGetter());
539 if (ModuleParams->Focus.ContainsID())
546 if (ModuleParams->Communicator.ContainsID())
549 auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(
ModuleData->Camera->GetInstrumentData());
550 ModuleData->CameraModes = CameraData->GetCameraModes();
577 ModuleData->Camera->SetCameraMode(Util::NumToT<size_t>(Index),
593 ModuleData->Camera->SetExposureTime(std::chrono::milliseconds(Value),
636 ModuleData->AutoSaveFilename = SaveFilename +
".png";
667 auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(
ModuleData->Camera->GetInstrumentData());
670 ModuleData->CaptureAfterPause = CameraData->IsCapturingContinuously();
672 if (ResetImageTransformation)
673 CameraData->SetImageTransformation({});
728 auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(
ModuleData->Camera->GetInstrumentData());
730 if (ResetImageTransformation)
731 CameraData->SetImageTransformation({});
733 ModuleData->CaptureAfterPause = CameraData->IsCapturingContinuously();
739 auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(
ModuleData->Camera->GetInstrumentData());
740 CameraData->SetComputeHistogram(CHT::NoHistogram);
751 bool ImageAvailable =
false;
754 auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(
ModuleData->Camera->GetInstrumentData());
756 ModuleData->CapturingState = CameraData->GetCapturingState();
757 ModuleData->MinExposureTime = CameraData->GetMinExposureTime();
758 ModuleData->MaxExposureTime = CameraData->GetMaxExposureTime();
759 ModuleData->CurrentExposureTime = CameraData->GetExposureTime();
760 ModuleData->CurrentFPS = CameraData->GetCurrentFPS();
762 CameraData->SetComputeHistogram(
ModuleData->ComputeHistogram);
764 ImageAvailable = CameraData->IsImageAvailbale() && !
ModuleData->ImageCapturingPaused;
767 ModuleData->CurrentImage = CameraData->GetImage();
770 if (
ModuleData->ComputeHistogram == CHT::IntensityHistogram ||
771 ModuleData->ComputeHistogram == CHT::IntensityAndRGBHistogram)
772 ModuleData->IntensityHistogram = CameraData->GetIntensityHistogram();
773 if (
ModuleData->ComputeHistogram == CHT::RGBHistogram ||
774 ModuleData->ComputeHistogram == CHT::IntensityAndRGBHistogram)
775 ModuleData->RGBHistogram = CameraData->GetRGBHistogram();
779 if (ImageAvailable && !
ModuleData->AutoSaveFilename.empty())
781 QImage Image =
ModuleData->CurrentImage.copy();
782 if (!Image.save(QString::fromStdString(
ModuleData->AutoSaveFilename)))
797 auto ModuleParams = DynExp::dynamic_Params_cast<ImageViewer>(Instance.
ParamsGetter());
808 AutofocusSamples.emplace_back(Voltage, std::numeric_limits<double>::quiet_NaN());
834 auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(
ModuleData->Camera->GetInstrumentData());
836 CameraData->ClearImage();
848 auto CameraData = DynExp::dynamic_InstrumentData_cast<DynExpInstr::Camera>(
ModuleData->Camera->GetInstrumentData());
850 if (CameraData->IsImageAvailbale())
852 ModuleData->CurrentExposureTime = CameraData->GetExposureTime();
853 ModuleData->CurrentImage = CameraData->GetImage();
871 return a.Result < b.Result;
882 AutofocusSamples.emplace_back(Voltage, std::numeric_limits<double>::quiet_NaN());
Implementation of a module to display images recorded by camera instruments.
@ CapturingSingle
The camera is caturing a single image and will stop afterwards.
@ CapturingContinuously
The camera is capturing one image after the other.
@ Stopped
The camera is not capturing.
float BrightnessFactor
Factor to enhance the image brightness (between -1 and 1).
bool IsEnabled
Determines whether the image transformation is to be applied (enabled).
ComputeHistogramType
Type indicating whether histograms should be computed for newly captured images.
@ NoHistogram
Histogram computation is disabled.
float ContrastFactor
Factor to enhance the image contrast. Valid interval is (0, Inf).
This event signals that an action (like a measurement) started by a TriggerEvent has been completed.
DynExpInstr::CameraData::TimeType TimeType
StateType AutofocusStepStateFunc(DynExp::ModuleInstance &Instance)
StateType AutofocusInitStateFunc(DynExp::ModuleInstance &Instance)
void FinishAutofocus(Util::SynchronizedPointer< ModuleDataType > &ModuleData, const FinishedAutofocusEvent &Event) const
void OnResumeImageCapturing(DynExp::ModuleInstance *Instance) const
void OnAutofocus(DynExp::ModuleInstance *Instance, bool ResetImageTransformation=false) const
StateType AutofocusFinishedStateFunc(DynExp::ModuleInstance &Instance)
void OnCaptureSingle(DynExp::ModuleInstance *Instance, bool) const
std::unique_ptr< DynExp::QModuleWidget > MakeUIWidget() override final
Used by InitUI() as a factory function for the module's user interface widget. Create the widget here...
void OnInit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread starts. Override it to lock instruments this m...
void OnSetFilename(DynExp::ModuleInstance *Instance, const std::string &SaveFilename) const
void OnStop(DynExp::ModuleInstance *Instance) const
Util::DynExpErrorCodes::DynExpErrorCodes ModuleMainLoop(DynExp::ModuleInstance &Instance) override final
Module main loop. The function is executed periodically by the module thread. Also refer to GetMainLo...
void OnCaptureContinuously(DynExp::ModuleInstance *Instance, bool Checked) const
bool IsAutofocusingState() const
AutofocusParamsType AutofocusParams
void OnTrigger(DynExp::ModuleInstance *Instance) const
StateType ReadyStateFunc(DynExp::ModuleInstance &Instance)
StateType AutofocusGotoSampleStateFunc(DynExp::ModuleInstance &Instance)
void OnExposureTimeChanged(DynExp::ModuleInstance *Instance, int Value) const
void OnExit(DynExp::ModuleInstance *Instance) const override final
This event is triggered right before the module thread terminates (not due to an exception,...
StateType AutofocusWaitForImageStateFunc(DynExp::ModuleInstance &Instance)
std::vector< AutofocusSampleType >::iterator AutofocusCurrentSample
std::vector< AutofocusSampleType > AutofocusSamples
StateType AutofocusWaitBeforeCaptureStateFunc(DynExp::ModuleInstance &Instance)
bool IsReadyState() const
bool AutofocusIsPerformingFineSweep
void OnAutofocusClicked(DynExp::ModuleInstance *Instance, bool Checked) const
void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter) override final
AutofocusResultsType AutofocusResults
const std::shared_ptr< std::atomic< bool > > PauseUpdatingUI
Util::StateMachine< StateMachineStateType > StateMachine
size_t NumFailedUpdateAttempts
void ResetImpl(dispatch_tag< QModuleBase >) override final
void OnCameraModeChanged(DynExp::ModuleInstance *Instance, int Index) const
void OnSaveImage(DynExp::ModuleInstance *Instance, QString Filename) const
std::chrono::system_clock::time_point AutofocusWaitingEndTimePoint
void OnPauseImageCapturing(DynExp::ModuleInstance *Instance, bool ResetImageTransformation=false) const
Wrapper holding a pointer to an exception and providing functionality for accessing it....
static void Register(const ModuleBase &Listener, CallableT EventFunc, ItemIDType CommunicatorID=ItemIDNotSet)
Registers/Subscribes module Listener to the event with the event function EventFunc....
static void Deregister(const ModuleBase &Listener)
Deregisters/unsubscribes module Listener from the event, regardless of the inter-module communicator ...
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
void MakeAndEnqueueEvent(ReceiverType *Receiver, EventType EventFuncPtr, ArgsTs &&...Args) const
Calls MakeEvent() to construct a new event and subsequently enqueues the event into the module's even...
Refer to ParamsBase::dispatch_tag.
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
const ModuleBase::ModuleDataGetterType ModuleDataGetter
Getter for module's data. Refer to ModuleBase::ModuleDataGetterType.
Refer to ParamsBase::dispatch_tag.
QModuleWidget * Widget
User interface widget belonging to the module.
void Connect(SenderType *Sender, SignalType Signal, ReceiverType *Receiver, EventType Event)
Uses Qt's connect mechanism to connect a QObject's signal to a DynExp module's event....
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
void UnlockObject(LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer)
Unlocks an Object instance stored in the LinkedObjectWrapperContainer ObjectWrapperContainer....
void LockObject(const ParamsBase::Param< ObjectLink< ObjectT > > &LinkParam, LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer, std::chrono::milliseconds Timeout=ObjectLinkBase::LockObjectTimeoutDefault)
Locks an Object instance referenced by a parameter LinkParam of type ParamsBase::Param< ObjectLink< O...
const auto & GetOwner() const noexcept
Returns Owner.
std::function< void(const TaskBase *, ExceptionContainer &)> FuncType
Type of the owned callback function. The function receives a pointer to the task the CallbackType ins...
Base class for all tasks being processed by instruments. The class must not contain public virtual fu...
void Log(const std::string &Message, const ErrorType Type=ErrorType::Info, const size_t Line=0, const std::string &Function="", const std::string &File="", const int ErrorCode=0, const std::stacktrace &Trace={}) noexcept
Logs an event from information specified manually.
Implements a QGraphicsView the user can interact with to insert graphical markers....
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
@ AutofocusWaitBeforeCapture
@ Unitless
Unitless scalar number.
@ UnitlessInt
Unitless scalar integer number.
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
DynExpErrorCodes
DynExp's error codes
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
std::array< unsigned long long, 256 > ImageHistogramType
Alias which represents a histogram as a std::array with 256 numeric bins. The lowest (highest) index ...
std::tuple< ImageHistogramType, ImageHistogramType, ImageHistogramType > ImageRGBHistogramType
Alias which represents a RGB histogram as a std::tuple of three ImageHistogramType elements....
QString PromptSaveFilePathModule(DynExp::QModuleWidget *Parent, const QString &Title, const QString &DefaultSuffix, const QString &NameFilter)
Works as PromptOpenFilePath() but asks the user to select a single file which does not need to exist....
Accumulates include statements to provide a precompiled header.
DynExpInstr::AnalogOutData::SampleStreamType::SampleType MinVoltage
ParamsConfigDialog::NumberType NumSteps
constexpr auto GetVoltageIncrement(bool Fine=false) const noexcept
DynExpInstr::AnalogOutData::SampleStreamType::SampleType MaxVoltage
std::chrono::milliseconds WaitTimeBeforeCapture