From 32969d24034b8d8fe16a93ea08996e79d9336dd9 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 15 Apr 2020 18:11:46 +1000 Subject: [PATCH] colordialog: updated to show input/reference/display values --- app/dialog/color/colordialog.cpp | 40 +++-- app/dialog/color/colordialog.h | 6 +- app/dialog/color/colorpreviewbox.cpp | 14 +- app/dialog/color/colorpreviewbox.h | 4 +- app/dialog/color/colorvalueswidget.cpp | 165 +++++++++++++++--- app/dialog/color/colorvalueswidget.h | 65 ++++++- .../backend/opengl/openglcolorprocessor.cpp | 8 +- .../backend/opengl/openglcolorprocessor.h | 6 +- app/render/colorprocessor.cpp | 13 +- app/render/colorprocessor.h | 11 +- app/widget/colorwheel/colorwheelwidget.cpp | 7 +- 11 files changed, 267 insertions(+), 72 deletions(-) diff --git a/app/dialog/color/colordialog.cpp b/app/dialog/color/colordialog.cpp index bad216cf8..44b4c90c8 100644 --- a/app/dialog/color/colordialog.cpp +++ b/app/dialog/color/colordialog.cpp @@ -60,14 +60,15 @@ ColorDialog::ColorDialog(ColorManager* color_manager, Color start, QString input value_layout->setSpacing(0); splitter->addWidget(value_area); - color_values_widget_ = new ColorValuesWidget(); + color_values_widget_ = new ColorValuesWidget(color_manager_); value_layout->addWidget(color_values_widget_); chooser_ = new ColorSpaceChooser(color_manager_); chooser_->set_input(input_cs); value_layout->addWidget(chooser_); - splitter->setSizes({INT_MAX, 0}); + // Split window 50/50 + splitter->setSizes({INT_MAX, INT_MAX}); connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, color_values_widget_, &ColorValuesWidget::SetColor); connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor); @@ -99,6 +100,7 @@ ColorDialog::ColorDialog(ColorManager* color_manager, Color start, QString input connect(chooser_, &ColorSpaceChooser::ColorSpaceChanged, this, &ColorDialog::ColorSpaceChanged); ColorSpaceChanged(chooser_->input(), chooser_->display(), chooser_->view(), chooser_->look()); + // Set default size ratio to 2:1 resize(sizeHint().height() * 2, sizeHint().height()); } @@ -107,8 +109,8 @@ Color ColorDialog::GetSelectedColor() const Color selected = color_wheel_->GetSelectedColor(); // Convert to linear and return a linear color - if (to_linear_processor_) { - return to_linear_processor_->ConvertColor(selected); + if (input_to_ref_processor_) { + return input_to_ref_processor_->ConvertColor(selected); } // Fallback if no processor is available @@ -137,17 +139,29 @@ QString ColorDialog::GetColorSpaceLook() const void ColorDialog::ColorSpaceChanged(const QString &input, const QString &display, const QString &view, const QString &look) { - to_linear_processor_ = ColorProcessor::Create(color_manager_->GetConfig(), input, color_manager_->GetReferenceColorSpace()); + input_to_ref_processor_ = ColorProcessor::Create(color_manager_->GetConfig(), input, color_manager_->GetReferenceColorSpace()); - ColorProcessorPtr to_display = ColorProcessor::Create(color_manager_->GetConfig(), - color_manager_->GetReferenceColorSpace(), - display, - view, - look); + ColorProcessorPtr ref_to_display = ColorProcessor::Create(color_manager_->GetConfig(), + color_manager_->GetReferenceColorSpace(), + display, + view, + look); - color_wheel_->SetColorProcessor(to_linear_processor_, to_display); - hsv_value_gradient_->SetColorProcessor(to_linear_processor_, to_display); - color_values_widget_->preview_box()->SetColorProcessor(to_linear_processor_, to_display); + ColorProcessorPtr ref_to_input = ColorProcessor::Create(color_manager_->GetConfig(), color_manager_->GetReferenceColorSpace(), input); + + // FIXME: For some reason, using OCIO::TRANSFORM_DIR_INVERSE (wrapped by ColorProcessor::kInverse) causes OCIO to + // crash. We've disabled that functionality for now (also disabling display_tab_ in ColorValuesWidget) + + /*ColorProcessorPtr display_to_ref = ColorProcessor::Create(color_manager_->GetConfig(), + color_manager_->GetReferenceColorSpace(), + display, + view, + look, + ColorProcessor::kInverse);*/ + + color_wheel_->SetColorProcessor(input_to_ref_processor_, ref_to_display); + hsv_value_gradient_->SetColorProcessor(input_to_ref_processor_, ref_to_display); + color_values_widget_->SetColorProcessor(input_to_ref_processor_, ref_to_display, nullptr, ref_to_input); } OLIVE_NAMESPACE_EXIT diff --git a/app/dialog/color/colordialog.h b/app/dialog/color/colordialog.h index 95f5e6310..7e6f2b8f7 100644 --- a/app/dialog/color/colordialog.h +++ b/app/dialog/color/colordialog.h @@ -77,11 +77,11 @@ private: ColorWheelWidget* color_wheel_; - ColorGradientWidget* hsv_value_gradient_; - ColorValuesWidget* color_values_widget_; - ColorProcessorPtr to_linear_processor_; + ColorGradientWidget* hsv_value_gradient_; + + ColorProcessorPtr input_to_ref_processor_; ColorSpaceChooser* chooser_; diff --git a/app/dialog/color/colorpreviewbox.cpp b/app/dialog/color/colorpreviewbox.cpp index f9f2eae1f..d15cfaf06 100644 --- a/app/dialog/color/colorpreviewbox.cpp +++ b/app/dialog/color/colorpreviewbox.cpp @@ -25,13 +25,15 @@ OLIVE_NAMESPACE_ENTER ColorPreviewBox::ColorPreviewBox(QWidget *parent) : - QWidget(parent) + QWidget(parent), + to_ref_processor_(nullptr), + to_display_processor_(nullptr) { } -void ColorPreviewBox::SetColorProcessor(ColorProcessorPtr to_linear, ColorProcessorPtr to_display) +void ColorPreviewBox::SetColorProcessor(ColorProcessorPtr to_ref, ColorProcessorPtr to_display) { - to_linear_processor_ = to_linear; + to_ref_processor_ = to_ref; to_display_processor_ = to_display; update(); @@ -50,8 +52,8 @@ void ColorPreviewBox::paintEvent(QPaintEvent *e) QColor c; // Color management - if (to_linear_processor_ && to_display_processor_) { - c = to_display_processor_->ConvertColor(to_linear_processor_->ConvertColor(color_)).toQColor(); + if (to_ref_processor_ && to_display_processor_) { + c = to_display_processor_->ConvertColor(to_ref_processor_->ConvertColor(color_)).toQColor(); } else { c = color_.toQColor(); } @@ -61,7 +63,7 @@ void ColorPreviewBox::paintEvent(QPaintEvent *e) p.setPen(Qt::black); p.setBrush(c); - p.drawRect(rect()); + p.drawRect(rect().adjusted(0, 0, -1, -1)); } OLIVE_NAMESPACE_EXIT diff --git a/app/dialog/color/colorpreviewbox.h b/app/dialog/color/colorpreviewbox.h index ab6a6e084..b7078e129 100644 --- a/app/dialog/color/colorpreviewbox.h +++ b/app/dialog/color/colorpreviewbox.h @@ -34,7 +34,7 @@ class ColorPreviewBox : public QWidget public: ColorPreviewBox(QWidget* parent = nullptr); - void SetColorProcessor(ColorProcessorPtr to_linear, ColorProcessorPtr to_display); + void SetColorProcessor(ColorProcessorPtr to_ref, ColorProcessorPtr to_display); public slots: void SetColor(const Color& c); @@ -45,7 +45,7 @@ protected: private: Color color_; - ColorProcessorPtr to_linear_processor_; + ColorProcessorPtr to_ref_processor_; ColorProcessorPtr to_display_processor_; diff --git a/app/dialog/color/colorvalueswidget.cpp b/app/dialog/color/colorvalueswidget.cpp index 91a1a1ea8..462d3c238 100644 --- a/app/dialog/color/colorvalueswidget.cpp +++ b/app/dialog/color/colorvalueswidget.cpp @@ -21,24 +21,149 @@ #include "colorvalueswidget.h" #include +#include OLIVE_NAMESPACE_ENTER -ColorValuesWidget::ColorValuesWidget(QWidget *parent) : +ColorValuesWidget::ColorValuesWidget(ColorManager *manager, QWidget *parent) : + QWidget(parent), + manager_(manager), + input_to_ref_(nullptr), + ref_to_display_(nullptr), + display_to_ref_(nullptr), + ref_to_input_(nullptr) +{ + QVBoxLayout* layout = new QVBoxLayout(this); + + // Create preview box + { + QHBoxLayout* preview_layout = new QHBoxLayout(); + + preview_layout->setMargin(0); + + preview_layout->addWidget(new QLabel(tr("Preview"))); + + preview_ = new ColorPreviewBox(); + preview_->setFixedHeight(fontMetrics().height() * 3 / 2); + preview_layout->addWidget(preview_); + + layout->addLayout(preview_layout); + } + + // Create value tabs + { + QTabWidget* tabs = new QTabWidget(); + + input_tab_ = new ColorValuesTab(); + tabs->addTab(input_tab_, tr("Input")); + connect(input_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::UpdateValuesFromInput); + connect(input_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::ColorChanged); + connect(input_tab_, &ColorValuesTab::ColorChanged, preview_, &ColorPreviewBox::SetColor); + + reference_tab_ = new ColorValuesTab(); + tabs->addTab(reference_tab_, tr("Reference")); + connect(reference_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::UpdateValuesFromRef); + + display_tab_ = new ColorValuesTab(); + tabs->addTab(display_tab_, tr("Display")); + connect(display_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::UpdateValuesFromDisplay); + + // FIXME: Display -> Ref temporarily disabled due to OCIO crash (see ColorDialog::ColorSpaceChanged for more info) + display_tab_->setEnabled(false); + + layout->addWidget(tabs); + } +} + +Color ColorValuesWidget::GetColor() const +{ + return reference_tab_->GetColor(); +} + +void ColorValuesWidget::SetColorProcessor(ColorProcessorPtr input_to_ref, ColorProcessorPtr ref_to_display, ColorProcessorPtr display_to_ref, ColorProcessorPtr ref_to_input) +{ + input_to_ref_ = input_to_ref; + ref_to_display_ = ref_to_display; + display_to_ref_ = display_to_ref; + ref_to_input_ = ref_to_input; + + UpdateValuesFromInput(); + + preview_->SetColorProcessor(input_to_ref_, ref_to_display_); +} + +void ColorValuesWidget::SetColor(const Color &c) +{ + input_tab_->SetColor(c); + preview_->SetColor(c); + + UpdateValuesFromInput(); +} + +void ColorValuesWidget::UpdateValuesFromInput() +{ + UpdateRefFromInput(); + UpdateDisplayFromRef(); +} + +void ColorValuesWidget::UpdateValuesFromRef() +{ + UpdateInputFromRef(); + UpdateDisplayFromRef(); +} + +void ColorValuesWidget::UpdateValuesFromDisplay() +{ + UpdateRefFromDisplay(); + UpdateInputFromRef(); +} + +void ColorValuesWidget::UpdateInputFromRef() +{ + if (ref_to_input_) { + input_tab_->SetColor(ref_to_input_->ConvertColor(reference_tab_->GetColor())); + } else { + input_tab_->SetColor(reference_tab_->GetColor()); + } + + preview_->SetColor(input_tab_->GetColor()); + emit ColorChanged(input_tab_->GetColor()); +} + +void ColorValuesWidget::UpdateDisplayFromRef() +{ + if (ref_to_display_) { + display_tab_->SetColor(ref_to_display_->ConvertColor(reference_tab_->GetColor())); + } else { + display_tab_->SetColor(reference_tab_->GetColor()); + } +} + +void ColorValuesWidget::UpdateRefFromInput() +{ + if (input_to_ref_) { + reference_tab_->SetColor(input_to_ref_->ConvertColor(input_tab_->GetColor())); + } else { + reference_tab_->SetColor(input_tab_->GetColor()); + } +} + +void ColorValuesWidget::UpdateRefFromDisplay() +{ + if (display_to_ref_) { + reference_tab_->SetColor(display_to_ref_->ConvertColor(display_tab_->GetColor())); + } else { + reference_tab_->SetColor(display_tab_->GetColor()); + } +} + +ColorValuesTab::ColorValuesTab(QWidget *parent) : QWidget(parent) { QGridLayout* layout = new QGridLayout(this); int row = 0; - layout->addWidget(new QLabel(tr("Preview")), row, 0); - - preview_ = new ColorPreviewBox(); - preview_->setFixedHeight(fontMetrics().height() * 3 / 2); - layout->addWidget(preview_, row, 1); - - row++; - layout->addWidget(new QLabel(tr("Red")), row, 0); red_slider_ = CreateColorSlider(); @@ -59,44 +184,34 @@ ColorValuesWidget::ColorValuesWidget(QWidget *parent) : layout->addWidget(blue_slider_, row, 1); } -Color ColorValuesWidget::GetColor() const +Color ColorValuesTab::GetColor() const { return Color(red_slider_->GetValue(), green_slider_->GetValue(), blue_slider_->GetValue()); } -ColorPreviewBox *ColorValuesWidget::preview_box() const -{ - return preview_; -} - -void ColorValuesWidget::SetColor(const Color &c) +void ColorValuesTab::SetColor(const Color &c) { red_slider_->SetValue(c.red()); green_slider_->SetValue(c.green()); blue_slider_->SetValue(c.blue()); - preview_->SetColor(c); } -FloatSlider *ColorValuesWidget::CreateColorSlider() +FloatSlider *ColorValuesTab::CreateColorSlider() { FloatSlider* fs = new FloatSlider(); fs->SetMinimum(0); fs->SetDragMultiplier(0.01); fs->SetMaximum(1); fs->SetDecimalPlaces(3); - connect(fs, &FloatSlider::ValueChanged, this, &ColorValuesWidget::SliderChanged); + connect(fs, &FloatSlider::ValueChanged, this, &ColorValuesTab::SliderChanged); return fs; } -void ColorValuesWidget::SliderChanged() +void ColorValuesTab::SliderChanged() { - Color c(red_slider_->GetValue(), green_slider_->GetValue(), blue_slider_->GetValue()); - - preview_->SetColor(c); - - emit ColorChanged(c); + emit ColorChanged(GetColor()); } OLIVE_NAMESPACE_EXIT diff --git a/app/dialog/color/colorvalueswidget.h b/app/dialog/color/colorvalueswidget.h index c8dfaf562..698900a17 100644 --- a/app/dialog/color/colorvalueswidget.h +++ b/app/dialog/color/colorvalueswidget.h @@ -25,21 +25,19 @@ #include "colorpreviewbox.h" #include "render/color.h" +#include "render/colormanager.h" #include "widget/slider/floatslider.h" OLIVE_NAMESPACE_ENTER -class ColorValuesWidget : public QWidget +class ColorValuesTab : public QWidget { Q_OBJECT public: - ColorValuesWidget(QWidget* parent = nullptr); + ColorValuesTab(QWidget* parent = nullptr); Color GetColor() const; - ColorPreviewBox* preview_box() const; - -public slots: void SetColor(const Color& c); signals: @@ -48,8 +46,6 @@ signals: private: FloatSlider* CreateColorSlider(); - ColorPreviewBox* preview_; - FloatSlider* red_slider_; FloatSlider* green_slider_; FloatSlider* blue_slider_; @@ -59,6 +55,61 @@ private slots: }; +class ColorValuesWidget : public QWidget +{ + Q_OBJECT +public: + ColorValuesWidget(ColorManager* manager, QWidget* parent = nullptr); + + Color GetColor() const; + + void SetColorProcessor(ColorProcessorPtr input_to_ref, + ColorProcessorPtr ref_to_display, + ColorProcessorPtr display_to_ref, + ColorProcessorPtr ref_to_input); + +public slots: + void SetColor(const Color& c); + +signals: + void ColorChanged(const Color& c); + +private: + void UpdateInputFromRef(); + + void UpdateDisplayFromRef(); + + void UpdateRefFromInput(); + + void UpdateRefFromDisplay(); + + ColorManager* manager_; + + ColorPreviewBox* preview_; + + ColorValuesTab* input_tab_; + + ColorValuesTab* reference_tab_; + + ColorValuesTab* display_tab_; + + ColorProcessorPtr input_to_ref_; + + ColorProcessorPtr ref_to_display_; + + ColorProcessorPtr display_to_ref_; + + ColorProcessorPtr ref_to_input_; + +private slots: + void UpdateValuesFromInput(); + + void UpdateValuesFromRef(); + + void UpdateValuesFromDisplay(); + +}; + OLIVE_NAMESPACE_EXIT #endif // COLORVALUESWIDGET_H diff --git a/app/render/backend/opengl/openglcolorprocessor.cpp b/app/render/backend/opengl/openglcolorprocessor.cpp index ddbe070d0..933d9e80c 100644 --- a/app/render/backend/opengl/openglcolorprocessor.cpp +++ b/app/render/backend/opengl/openglcolorprocessor.cpp @@ -77,8 +77,8 @@ OpenGLColorProcessor::OpenGLColorProcessor(OCIO::ConstConfigRcPtr config, const { } -OpenGLColorProcessor::OpenGLColorProcessor(OCIO::ConstConfigRcPtr config, const QString &source_space, QString display, QString view, const QString &look) : - ColorProcessor(config, source_space, display, view, look), +OpenGLColorProcessor::OpenGLColorProcessor(OCIO::ConstConfigRcPtr config, const QString &source_space, QString display, QString view, const QString &look, Direction dir) : + ColorProcessor(config, source_space, display, view, look, dir), ocio_lut_(0) { } @@ -93,9 +93,9 @@ OpenGLColorProcessorPtr OpenGLColorProcessor::Create(OCIO::ConstConfigRcPtr conf return std::make_shared(config, source_space, dest_space); } -OpenGLColorProcessorPtr OpenGLColorProcessor::Create(OCIO::ConstConfigRcPtr config, const QString &source_space, const QString &display, const QString &view, const QString &look) +OpenGLColorProcessorPtr OpenGLColorProcessor::Create(OCIO::ConstConfigRcPtr config, const QString &source_space, const QString &display, const QString &view, const QString &look, Direction dir) { - return std::make_shared(config, source_space, display, view, look); + return std::make_shared(config, source_space, display, view, look, dir); } OLIVE_NAMESPACE_EXIT diff --git a/app/render/backend/opengl/openglcolorprocessor.h b/app/render/backend/opengl/openglcolorprocessor.h index 67929fe1d..53cb43861 100644 --- a/app/render/backend/opengl/openglcolorprocessor.h +++ b/app/render/backend/opengl/openglcolorprocessor.h @@ -39,7 +39,8 @@ public: const QString& source_space, QString display, QString view, - const QString& look); + const QString& look, + Direction dir); ~OpenGLColorProcessor(); @@ -49,7 +50,8 @@ public: const QString& source_space, const QString& display, const QString& view, - const QString& look); + const QString& look, + Direction dir = kNormal); void Enable(QOpenGLContext* context, bool alpha_is_associated); bool IsEnabled() const; diff --git a/app/render/colorprocessor.cpp b/app/render/colorprocessor.cpp index 24e3bdfe5..252be8c85 100644 --- a/app/render/colorprocessor.cpp +++ b/app/render/colorprocessor.cpp @@ -34,7 +34,8 @@ ColorProcessor::ColorProcessor(OCIO::ConstConfigRcPtr config, const QString& source_space, QString display, QString view, - const QString& look) + const QString& look, + Direction direction) { if (display.isEmpty()) { display = config->getDefaultDisplay(); @@ -55,7 +56,9 @@ ColorProcessor::ColorProcessor(OCIO::ConstConfigRcPtr config, transform->setLooksOverrideEnabled(true); } - processor = config->getProcessor(transform); + OCIO::TransformDirection dir = (direction == kInverse) ? OCIO::TRANSFORM_DIR_INVERSE : OCIO::TRANSFORM_DIR_FORWARD; + + processor = config->getProcessor(transform, dir); } void ColorProcessor::ConvertFrame(FramePtr f) @@ -76,12 +79,12 @@ ColorProcessorPtr ColorProcessor::Create(OCIO::ConstConfigRcPtr config, const QS return std::make_shared(config, source_space, dest_space); } -ColorProcessorPtr ColorProcessor::Create(OCIO::ConstConfigRcPtr config, const QString &source_space, const QString &display, const QString &view, const QString &look) +ColorProcessorPtr ColorProcessor::Create(OCIO::ConstConfigRcPtr config, const QString &source_space, const QString &display, const QString &view, const QString &look, Direction direction) { - return std::make_shared(config, source_space, display, view, look); + return std::make_shared(config, source_space, display, view, look, direction); } -OpenColorIO::v1::ConstProcessorRcPtr ColorProcessor::GetProcessor() +OCIO::ConstProcessorRcPtr ColorProcessor::GetProcessor() { return processor; } diff --git a/app/render/colorprocessor.h b/app/render/colorprocessor.h index abc7129d5..391d5ccac 100644 --- a/app/render/colorprocessor.h +++ b/app/render/colorprocessor.h @@ -35,12 +35,18 @@ using ColorProcessorPtr = std::shared_ptr; class ColorProcessor { public: + enum Direction { + kNormal, + kInverse + }; + ColorProcessor(OCIO::ConstConfigRcPtr config, const QString &source_space, const QString &dest_space); ColorProcessor(OCIO::ConstConfigRcPtr config, const QString& source_space, QString display, QString view, - const QString& look); + const QString& look, + Direction direction); DISABLE_COPY_MOVE(ColorProcessor) @@ -50,7 +56,8 @@ public: const QString& source_space, const QString& display, const QString& view, - const QString& look); + const QString& look, + Direction direction = kNormal); OCIO::ConstProcessorRcPtr GetProcessor(); diff --git a/app/widget/colorwheel/colorwheelwidget.cpp b/app/widget/colorwheel/colorwheelwidget.cpp index 379531768..3d9872146 100644 --- a/app/widget/colorwheel/colorwheelwidget.cpp +++ b/app/widget/colorwheel/colorwheelwidget.cpp @@ -55,8 +55,8 @@ void ColorWheelWidget::paintEvent(QPaintEvent *e) int diameter = GetDiameter(); - // Half diameter (add one to ensure the division rounds up) - int radius = (diameter + 1) / 2; + // Half diameter + int radius = diameter / 2; if (cached_wheel_.width() != diameter || force_redraw_) { cached_wheel_ = QPixmap(QSize(diameter, diameter)); @@ -71,7 +71,8 @@ void ColorWheelWidget::paintEvent(QPaintEvent *e) Triangle tri = GetTriangleFromCoords(center, j, i); if (tri.hypotenuse <= radius) { - QColor c = GetManagedColor(GetColorFromTriangle(tri)).toQColor(); + Color managed = GetManagedColor(GetColorFromTriangle(tri)); + QColor c = managed.toQColor(); // Very basic antialiasing around the edges of the wheel qreal alpha = qMin(1.0, radius - tri.hypotenuse);