#include "main_widget.hpp"
#include <cvb/image.hpp>
#include <cvb/utilities/system_info.hpp>
#include <cvb/ui/ui.hpp>
#include <cvb/ui/opengl_image_renderer_factory.hpp>
PTResultWidget::PTResultWidget()
: QTableWidget()
{
setWindowIcon(QIcon(":/qttutorial.png"));
for (int i = 0; i < 7; i++)
insertColumn(0);
QStringList lables;
lables << "Image Size" << "View Size" << "Zoom" << "Format" << "Upload" << "Rendering" << "FPs";
setHorizontalHeaderLabels(lables);
auto* header = horizontalHeader();
header->setSectionResizeMode(QHeaderView::Stretch);
auto font = header->font();
font.setBold(true);
header->setFont(font);
resize(640, 480);
setWindowTitle("Performance Test Results");
}
void PTResultWidget::AddResult(const PTResult& result)
{
auto row = rowCount();
insertRow(row);
SetResultItem(row, 0, ImageSizeToString(result.ImageSize));
SetResultItem(row, 1, ViewSizeToString(result.ViewSize));
SetResultItem(row, 2, ZoomToString(result.Zoom));
SetResultItem(row, 3, PlanesToString(result.Planes));
SetResultItem(row, 4, UploadModeToString(result.UploadMode));
QString renderEngineToolTip;
if (result.RenderEngine == Cvb::UI::RenderEngine::Raster)
{
renderEngineToolTip = QString("Rendered with \"QPainter\"");
}
else
{
int glVersion = (result.RenderEngine == Cvb::UI::RenderEngine::OpenGL2) ? 2 : 3;
renderEngineToolTip = vendor + QString("\n") + renderer;
}
SetResultItem(row, 5, RenderEngineToString(result.RenderEngine), renderEngineToolTip);
SetResultItem(row, 6, FPsToString(result.FPS));
}
void PTResultWidget::SetResultItem(int row, int column, const QString & text, const QString & toolTip)
{
auto cell = new QTableWidgetItem(text);
cell->setTextAlignment(Qt::AlignCenter);
cell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
if (!toolTip.isEmpty())
cell->setToolTip(toolTip);
setItem(row, column, cell);
}
{
return QString(
"%1 x ").arg(size.
Width()) + QString(
"%1").arg(size.
Height());
}
QString PTResultWidget::ViewSizeToString(QSize size) const
{
return QString("%1 x ").arg(size.width()) + QString("%1").arg(size.height());
}
{
switch (zoomDescriptor.
ID)
{
default:
case Cvb::UI::ZoomID::Invalid:
return "Invalid";
case Cvb::UI::ZoomID::Panorama:
return "Panorama";
case Cvb::UI::ZoomID::Factor1:
return "1 : 1";
case Cvb::UI::ZoomID::Factor2:
return "1 : 2";
case Cvb::UI::ZoomID::Factor4:
return "1 : 4";
case Cvb::UI::ZoomID::Factor8:
return "1 : 8";
case Cvb::UI::ZoomID::Factor16:
return "1 : 16";
case Cvb::UI::ZoomID::Factor32:
return "1 : 32";
case Cvb::UI::ZoomID::Factor64:
return "1 : 64";
case Cvb::UI::ZoomID::Factor128:
return "1 : 128";
}
}
QString PTResultWidget::PlanesToString(int planes) const
{
return (planes == 1) ? "Mono" : "Colour";
}
{
return (uploadMode == Cvb::UI::UploadMode::Image) ? "Image" : "View";
}
{
switch (renderEngine)
{
default:
return "Invalid";
case Cvb::UI::RenderEngine::Raster:
return "Raster";
case Cvb::UI::RenderEngine::OpenGL2:
return "OpenGL 2";
case Cvb::UI::RenderEngine::OpenGL3:
return "OpenGL 3";
}
}
QString PTResultWidget::FPsToString(double fps) const
{
return QString("%1").arg(fps, 3);
}
PTSetupWidget::PTSetupWidget(QWidget * parent, PTResultWidget * ptResultWidget)
: QWidget(parent)
, ptResultWidget_(ptResultWidget)
{
spMeasurementCount_ = new QSpinBox(this);
spRefreshCount_ = new QSpinBox(this);
auto pbHide = new QPushButton("Hide");
auto pbHideAndRunPT = new QPushButton("Hide & Run");
auto groupBox = new QGroupBox("Performance Test for Render Engine");
auto mainLayout = new QVBoxLayout;
auto spLayout = new QVBoxLayout;
auto pbLayout = new QHBoxLayout;
spLayout->addWidget(spMeasurementCount_);
spLayout->addWidget(spRefreshCount_);
pbLayout->addStretch();
pbLayout->addWidget(pbHide);
pbLayout->addWidget(pbHideAndRunPT);
pbLayout->addStretch();
mainLayout->addLayout(spLayout);
mainLayout->addLayout(pbLayout);
groupBox->setLayout(mainLayout);
auto gblayout = new QVBoxLayout;
gblayout->addWidget(groupBox);
setLayout(gblayout);
spMeasurementCount_->setPrefix("Measurement Count: ");
spMeasurementCount_->setRange(2, 10000);
spMeasurementCount_->setValue(measurementCount_);
spMeasurementCount_->setToolTip("Number of measurements used to get a result as mean.");
spRefreshCount_->setPrefix("Refresh Count: ");
spRefreshCount_->setRange(500, 1000000);
spRefreshCount_->setValue(refreshCount_);
spRefreshCount_->setToolTip("Number of display refreshes executed for a single measurement.");
connect(spMeasurementCount_, SIGNAL(valueChanged(int)), this, SLOT(HandleMeasurementCountChanged(int)));
connect(spRefreshCount_, SIGNAL(valueChanged(int)), this, SLOT(HandleRefreshCountChanged(int)));
connect(pbHide, SIGNAL(clicked()), this, SLOT(HandleHide()));
connect(pbHideAndRunPT, SIGNAL(clicked()), this, SLOT(HandleHideAndRunPT()));
}
void PTSetupWidget::HandleHide() noexcept
{
setVisible(false);
}
void PTSetupWidget::HandleHideAndRunPT() noexcept
{
HandleHide();
if (!ptResultWidget_->isVisible())
{
ptResultWidget_->move(QApplication::desktop()->screen()->rect().center());
ptResultWidget_->show();
}
RunPT();
}
void PTSetupWidget::HandleRefreshCountChanged(int value) noexcept
{
refreshCount_ = value;
}
void PTSetupWidget::HandleMeasurementCountChanged(int value) noexcept
{
measurementCount_ = value;
}
MainWidget::MainWidget(PTResultWidget * ptResultWidget)
: QWidget()
, ptResultWidget_(ptResultWidget)
{
ptSetupWidget_ = new PTSetupWidget(this, ptResultWidget_);
auto mainLayout = new QVBoxLayout;
mainLayout->addWidget(imageView_);
mainLayout->addWidget(new QLabel(tr("Right click to get the context menu."), this));
mainLayout->addWidget(ptSetupWidget_);
setLayout(mainLayout);
imageView_->Refresh(image);
performaceTimer_.setTimerType(Qt::TimerType::PreciseTimer);
connect(ptSetupWidget_, SIGNAL(RunPT()), this, SLOT(HandlePT()));
connect(&performaceTimer_, SIGNAL(timeout()), this, SLOT(HandleTimeout()));
ptSetupWidget_->hide();
}
void MainWidget::HandleLoadImage()
{
auto fileName = QFileDialog::getOpenFileName(
this,
"Load Image",
Cvb::UI::CvbToQt(
Cvb::InstallPath()),
"Images(*.bmp *.png *.tif *.tiff *.jpg);;Common Vision Blox Image Object(*.mio)");
if (fileName.isEmpty())
return;
try
{
imageView_->Refresh(image);
}
catch (const std::exception& error)
{
QMessageBox::critical(this, "Error", QString(error.what()));
}
}
void MainWidget::HandlePixelValue()
{
if (!mouseMoveCookie_)
{
mouseMoveCookie_ = imageView_->RegisterEventMouseMoved([&](
Cvb::Point2D<int> mousePos,
const std::vector<double>& pixelVal)
{
titleStream <<
"(X:" << mousePos.
X() <<
", Y:" << mousePos.
Y() <<
") ";
if (pixelVal.size() == 3)
titleStream << "(R:" << qFloor(pixelVal[0]) << ", G:" << qFloor(pixelVal[1]) << ", B:" << qFloor(pixelVal[2]) << ")";
else if (pixelVal.size() == 1)
titleStream << "(V:" << qFloor(pixelVal[0]) << ")";
});
}
else
{
imageView_->UnregisterEventMouseMoved(mouseMoveCookie_);
setWindowTitle("");
}
}
void MainWidget::HandleRenderEngineChanged(QAction* action)
{
try
{
imageView_->SetRenderEngine(renderEngine);
imageView_->Refresh();
}
catch (const std::exception& error)
{
QMessageBox::critical(this, "Error", QString(error.what()) + QString("\nCheck your graphics driver!"));
}
}
void MainWidget::HandleUploadModeChange(QAction* action)
{
try
{
imageView_->SetUploadMode(uploadMode);
}
catch (const std::exception& error)
{
QMessageBox::critical(this, "Error", QString(error.what()));
}
}
void MainWidget::HandlePT()
{
ptState_ = PTState::Running;
rateCounter_.SetWindowSize(ptSetupWidget_->MeasurementCout());
testCycles_ = 0;
ShowProgress();
performaceTimer_.start();
}
void MainWidget::HandleTimeout()
{
if (testCycles_ % ptSetupWidget_->RefreshCount() == 0)
{
rateCounter_.Step();
ShowProgress();
if (rateCounter_.NumSteps() == rateCounter_.WindowSize())
{
performaceTimer_.stop();
if (ptState_ == PTState::Running)
{
auto rate = rateCounter_.Rate();
AppendResult(rate * static_cast<double>(ptSetupWidget_->RefreshCount()));
rateCounter_.Reset();
ptState_ = PTState::Idle;
setWindowTitle("");
}
}
}
imageView_->Refresh();
testCycles_++;
}
void MainWidget::HandleClearResults()
{
while (ptResultWidget_->rowCount())
ptResultWidget_->removeRow(0);
}
void MainWidget::ShowProgress() noexcept
{
ptResultWidget_->setWindowTitle(QString("Performance Test ")
+ ((ptState_ == PTState::Running) ? QString("Running") : QString("Setup"))
+ QString(": %1").arg(rateCounter_.NumSteps())
+ QString(" / %1").arg(rateCounter_.WindowSize()));
}
void MainWidget::AppendResult(double fps)
{
PTResult result;
result.Planes = imageView_->Image()->PlanesCount();
result.FPS = fps;
result.RenderEngine = imageView_->RenderEngine();
result.ViewSize = imageView_->size();
result.ImageSize = imageView_->Image()->Size();
result.UploadMode = imageView_->UploadMode();
result.Zoom = imageView_->Zoom();
ptResultWidget_->setWindowTitle("Performance Test Results");
ptResultWidget_->AddResult(result);
}
void MainWidget::contextMenuEvent(QContextMenuEvent *event)
{
if (windowState() & Qt::WindowFullScreen
|| ptState_ != PTState::Idle)
return;
QMenu contextMenu;
auto acLoadImage = contextMenu.addAction("Load Image");
contextMenu.addSeparator();
auto acShowFullScreen = contextMenu.addAction("Show Full Screen");
auto acPixelValues = contextMenu.addAction("Pixel Values");
acPixelValues->setCheckable(true);
acPixelValues->setChecked(static_cast<bool>(mouseMoveCookie_));
contextMenu.addSeparator();
auto mnRenderEngine = contextMenu.addMenu("Render Engine");
QActionGroup* agRenderEngine = new QActionGroup(&contextMenu);
agRenderEngine->setExclusive(true);
auto acRenderEngineRaster = agRenderEngine->addAction("Raster");
acRenderEngineRaster->setCheckable(true);
acRenderEngineRaster->setData(static_cast<int>(Cvb::UI::RenderEngine::Raster));
auto acRenderEngineGL2 = agRenderEngine->addAction("OpenGL 2");
acRenderEngineGL2->setCheckable(true);
acRenderEngineGL2->setData(static_cast<int>(Cvb::UI::RenderEngine::OpenGL2));
auto acRenderEngineGL3 = agRenderEngine->addAction("OpenGL 3");
acRenderEngineGL3->setCheckable(true);
acRenderEngineGL3->setData(static_cast<int>(Cvb::UI::RenderEngine::OpenGL3));
switch (imageView_->RenderEngine())
{
default:
case Cvb::UI::RenderEngine::Raster:
acRenderEngineRaster->setChecked(true);
break;
case Cvb::UI::RenderEngine::OpenGL2:
acRenderEngineGL2->setChecked(true);
break;
case Cvb::UI::RenderEngine::OpenGL3:
acRenderEngineGL3->setChecked(true);
break;
}
mnRenderEngine->addActions(agRenderEngine->actions());
auto mnUploadMode = contextMenu.addMenu("Upload Mode");
QActionGroup* agUploadMode = new QActionGroup(&contextMenu);
agUploadMode->setExclusive(true);
auto acUploadModeViewPort = agUploadMode->addAction("Viewport");
acUploadModeViewPort->setCheckable(true);
acUploadModeViewPort->setData(static_cast<int>(Cvb::UI::UploadMode::Viewport));
auto acUploadModeImage = agUploadMode->addAction("Image");
acUploadModeImage->setCheckable(true);
acUploadModeImage->setData(static_cast<int>(Cvb::UI::UploadMode::Image));
switch (imageView_->UploadMode())
{
default:
case Cvb::UI::UploadMode::Viewport:
acUploadModeViewPort->setChecked(true);
break;
case Cvb::UI::UploadMode::Image:
acUploadModeImage->setChecked(true);
break;
}
mnUploadMode->addActions(agUploadMode->actions());
auto mnPT = contextMenu.addMenu("Performance Test");
auto acSetupTest = mnPT->addAction("Setup Test");
auto acShowResults = mnPT->addAction("Show Results");
auto acClearResults = mnPT->addAction("Clear Results");
connect(acLoadImage, SIGNAL(triggered()), this, SLOT(HandleLoadImage()));
connect(acPixelValues, SIGNAL(triggered()), this, SLOT(HandlePixelValue()));
connect(agRenderEngine, SIGNAL(triggered(QAction*)), this, SLOT(HandleRenderEngineChanged(QAction*)));
connect(agUploadMode, SIGNAL(triggered(QAction*)), this, SLOT(HandleUploadModeChange(QAction*)));
connect(acShowFullScreen, SIGNAL(triggered()), this, SLOT(showFullScreen()));
connect(acSetupTest, SIGNAL(triggered()), ptSetupWidget_, SLOT(show()));
connect(acShowResults, SIGNAL(triggered()), ptResultWidget_, SLOT(show()));
connect(acClearResults, SIGNAL(triggered()), this, SLOT(HandleClearResults()));
contextMenu.exec(mapToGlobal(event->pos()));
}
void MainWidget::keyPressEvent(QKeyEvent *event)
{
if (ptState_ == PTState::Running)
{
QWidget::keyPressEvent(event);
return;
}
if ((event->key() == Qt::Key_T) && QApplication::keyboardModifiers() && Qt::ControlModifier)
{
if (ptSetupWidget_->isVisible())
ptSetupWidget_->hide();
else
ptSetupWidget_->show();
}
else if ((event->key() == Qt::Key_F) && QApplication::keyboardModifiers() && Qt::ControlModifier)
{
if (isFullScreen())
showNormal();
else
showFullScreen();
}
else if ((event->key() == Qt::Key_R) && QApplication::keyboardModifiers() && Qt::ControlModifier)
{
if (ptResultWidget_->isVisible())
ptResultWidget_->close();
else
ptResultWidget_->show();
}
else if (event->key() == Qt::Key_Escape)
{
if (isFullScreen())
showNormal();
}
}
static std::unique_ptr< Image > Load(const String &fileName)
T Height() const noexcept
static String VendorName(int version)
static String RendererName(int version)
Cvb::String QtToCvb(const QString text) noexcept
QString CvbToQt(const Cvb::String &text) noexcept
String ExpandPath(const String &path)
std::shared_ptr< Image > ImagePtr
std::stringstream StringStream
cvb.Image resize(cvb.Image image, cvb.Size2D target_size, int interpolation=cvb.foundation.Interpolation.Linear)