From bdb13e88f5ec8b514db50a61839e7410cca40ea1 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 21 Apr 2020 01:29:08 +1000 Subject: [PATCH] histogram: implemented histogram widget --- app/panel/scope/scope.cpp | 8 +- app/panel/scope/scope.h | 5 + app/panel/viewer/viewerbase.cpp | 1 + app/widget/scope/histogram/histogram.cpp | 150 ++++++++++++++++++++++- app/widget/scope/histogram/histogram.h | 47 +++++++ 5 files changed, 208 insertions(+), 3 deletions(-) diff --git a/app/panel/scope/scope.cpp b/app/panel/scope/scope.cpp index 4073a70af..ef6678311 100644 --- a/app/panel/scope/scope.cpp +++ b/app/panel/scope/scope.cpp @@ -57,7 +57,8 @@ ScopePanel::ScopePanel(QWidget* parent) : stack_->addWidget(waveform_view_); // Create histogram - stack_->addWidget(new QWidget()); + histogram_ = new HistogramScope(); + stack_->addWidget(histogram_); connect(scope_type_combobox_, static_cast(&QComboBox::currentIndexChanged), stack_, &QStackedWidget::setCurrentIndex); @@ -88,6 +89,11 @@ void ScopePanel::DrewManagedTexture(OpenGLTexture *texture) waveform_view_->SetTexture(texture); } +void ScopePanel::SetBuffer(Frame *frame) +{ + histogram_->SetBuffer(frame); +} + void ScopePanel::Retranslate() { SetTitle(tr("Scope")); diff --git a/app/panel/scope/scope.h b/app/panel/scope/scope.h index 3256ad1fc..48c63518c 100644 --- a/app/panel/scope/scope.h +++ b/app/panel/scope/scope.h @@ -25,6 +25,7 @@ #include #include "widget/panel/panel.h" +#include "widget/scope/histogram/histogram.h" #include "widget/scope/waveform/waveform.h" OLIVE_NAMESPACE_ENTER @@ -51,6 +52,8 @@ public: public slots: void DrewManagedTexture(OpenGLTexture* texture); + void SetBuffer(Frame* frame); + protected: virtual void Retranslate() override; @@ -63,6 +66,8 @@ private: WaveformScope* waveform_view_; + HistogramScope* histogram_; + }; OLIVE_NAMESPACE_EXIT diff --git a/app/panel/viewer/viewerbase.cpp b/app/panel/viewer/viewerbase.cpp index f53bb42bc..937692788 100644 --- a/app/panel/viewer/viewerbase.cpp +++ b/app/panel/viewer/viewerbase.cpp @@ -106,6 +106,7 @@ void ViewerPanelBase::CreateScopePanel(ScopePanel::Type type) // Connect viewer widget texture drawing to scope panel connect(vw, &ViewerWidget::DrewManagedTexture, p, &ScopePanel::DrewManagedTexture); + connect(vw, &ViewerWidget::LoadedBuffer, p, &ScopePanel::SetBuffer); if (!scope_panel_count_) { vw->SetEmitDrewManagedTextureEnabled(true); diff --git a/app/widget/scope/histogram/histogram.cpp b/app/widget/scope/histogram/histogram.cpp index 1f4a13543..a4c9097cd 100644 --- a/app/widget/scope/histogram/histogram.cpp +++ b/app/widget/scope/histogram/histogram.cpp @@ -20,23 +20,169 @@ #include "histogram.h" +#include +#include + +#include "common/clamp.h" +#include "common/functiontimer.h" + OLIVE_NAMESPACE_ENTER HistogramScope::HistogramScope(QWidget* parent) : - QOpenGLWidget(parent) + QOpenGLWidget(parent), + buffer_(nullptr) { + connect(&worker_, &HistogramScopeWorker::Finished, this, &HistogramScope::FinishedProcessing, Qt::QueuedConnection); + worker_.start(QThread::IdlePriority); +} + +HistogramScope::~HistogramScope() +{ + worker_.Cancel(); + worker_.quit(); + worker_.wait(); } void HistogramScope::SetBuffer(Frame* frame) { + // We'll be multithreading this, so we make a copy to prevent collisions buffer_ = frame; + StartUpdate(); +} + +void HistogramScope::FinishedProcessing(QVector red, QVector green, QVector blue) +{ + red_val_ = red; + green_val_ = green; + blue_val_ = blue; + update(); } void HistogramScope::paintGL() { - //QPainter p(this); + QVector red_lines(red_val_.size()); + QVector green_lines(green_val_.size()); + QVector blue_lines(blue_val_.size()); + + for (int i=0;i data(w * kRGBChannels, 0); + + int max_w = w-1; + + for (int x=0;x max_val) { + max_val = i; + } + } + + if (!max_val) { + // Prevent divide by zero + return; + } + + QVector red_lines(w); + QVector green_lines(w); + QVector blue_lines(w); + + for (int i=0;i(data.at(i)) / static_cast(max_val)); + green_lines.replace(i, static_cast(data.at(i + w)) / static_cast(max_val)); + blue_lines.replace(i, static_cast(data.at(i + w * 2)) / static_cast(max_val)); + } + + emit Finished(red_lines, green_lines, blue_lines); + } +} + +void HistogramScopeWorker::QueueNext(const Frame &f, int width) +{ + next_lock_.lock(); + + next_ = f; + next_width_ = width; + + next_wait_.wakeOne(); + + next_lock_.unlock(); +} + +void HistogramScopeWorker::Cancel() +{ + cancelled_ = true; + next_lock_.lock(); + next_wait_.wakeOne(); + next_lock_.unlock(); } OLIVE_NAMESPACE_EXIT diff --git a/app/widget/scope/histogram/histogram.h b/app/widget/scope/histogram/histogram.h index 973bb1f94..b4b94527e 100644 --- a/app/widget/scope/histogram/histogram.h +++ b/app/widget/scope/histogram/histogram.h @@ -21,27 +21,74 @@ #ifndef HISTOGRAMSCOPE_H #define HISTOGRAMSCOPE_H +#include #include +#include +#include #include "codec/frame.h" OLIVE_NAMESPACE_ENTER +class HistogramScopeWorker : public QThread +{ + Q_OBJECT +public: + HistogramScopeWorker(); + + virtual void run() override; + + // Thread-safe + void QueueNext(const Frame& f, int width); + + void Cancel(); + +signals: + void Finished(QVector red, QVector green, QVector blue); + +private: + QAtomicInt cancelled_; + + QMutex next_lock_; + QWaitCondition next_wait_; + Frame next_; + int next_width_; + +}; + class HistogramScope : public QOpenGLWidget { Q_OBJECT public: HistogramScope(QWidget* parent = nullptr); + virtual ~HistogramScope() override; + public slots: void SetBuffer(Frame* frame); protected: +// virtual void paintEvent(QPaintEvent* e) override; virtual void paintGL() override; + virtual void resizeEvent(QResizeEvent* e) override; + private: + void StartUpdate(); + Frame* buffer_; + QVector red_val_; + + QVector green_val_; + + QVector blue_val_; + + HistogramScopeWorker worker_; + +private slots: + void FinishedProcessing(QVector red, QVector green, QVector blue); + }; OLIVE_NAMESPACE_EXIT