From e4701101c91eb667abfd0eb24ed310e771154b30 Mon Sep 17 00:00:00 2001 From: Pandagrapher Date: Thu, 15 Aug 2019 10:26:44 +0200 Subject: [PATCH] Creation of generic class to manage Locallab tools Notes: - All Locallab tools have been converted to this new design - Locallab GUI hasn't been updated to this new design Bugfix: Solve crash problem when using ctrl+copy/ctrl+paste --- rtengine/procparams.cc | 56 +- rtengine/procparams.h | 6 + rtgui/CMakeLists.txt | 2 + rtgui/locallab.cc | 5 + rtgui/locallabtools.cc | 2539 ++++++++++++++++++++++++++++++++++++++ rtgui/locallabtools.h | 654 ++++++++++ rtgui/locallabtools2.cc | 2121 +++++++++++++++++++++++++++++++ rtgui/partialpastedlg.cc | 3 + 8 files changed, 5361 insertions(+), 25 deletions(-) create mode 100644 rtgui/locallabtools.cc create mode 100644 rtgui/locallabtools.h create mode 100644 rtgui/locallabtools2.cc diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index f3e0111ea..e58853346 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2381,15 +2381,15 @@ LocallabParams::LocallabSpot::LocallabSpot() : slomaskcol(0.0), qualitycurveMethod("none"), gridMethod("one"), - llcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, - cccurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, - LHcurve{(double)FCT_MinMaxCPoints, 0.0, 0.50, 0.35, 0.35, 0.166, 0.50, 0.35, 0.35, 0.333, 0.50, 0.35, 0.35, 0.50, 0.50, 0.35, 0.35, 0.666, 0.50, 0.35, 0.35, 0.833, 0.50, 0.35, 0.35}, - HHcurve{(double)FCT_MinMaxCPoints, 0.0, 0.50, 0.35, 0.35, 0.166, 0.50, 0.35, 0.35, 0.333, 0.50, 0.35, 0.35, 0.50, 0.50, 0.35, 0.35, 0.666, 0.50, 0.35, 0.35, 0.833, 0.50, 0.35, 0.35}, + llcurve(DEF_COLOR_LCURVE), + cccurve(DEF_COLOR_LCURVE), + LHcurve(DEF_COLOR_HCURVE), + HHcurve(DEF_COLOR_HCURVE), invers(false), enaColorMask(false), - CCmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.00, 1.0, 0.35, 0.35 }, - LLmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.00, 1.0, 0.35, 0.35 }, - HHmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.00, 1.0, 0.35, 0.35 }, + CCmaskcurve(DEF_MASK_CURVE), + LLmaskcurve(DEF_MASK_CURVE), + HHmaskcurve(DEF_MASK_CURVE), softradiuscol(0.0), // Exposure expexpose(false), @@ -2404,12 +2404,12 @@ LocallabParams::LocallabSpot::LocallabSpot() : sensiex(15), structexp(0), blurexpde(5), - excurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, + excurve(DEF_EXP_CURVE), inversex(false), enaExpMask(false), - CCmaskexpcurve{(double)FCT_MinMaxCPoints,0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35 }, - LLmaskexpcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, - HHmaskexpcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + CCmaskexpcurve(DEF_MASK_CURVE), + LLmaskexpcurve(DEF_MASK_CURVE), + HHmaskexpcurve(DEF_MASK_CURVE), blendmaskexp(0), radmaskexp(10.0), chromaskexp(0.0), @@ -2429,9 +2429,9 @@ LocallabParams::LocallabSpot::LocallabSpot() : sh_radius(40), sensihs(15), enaSHMask(false), - CCmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35 }, - LLmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, - HHmaskSHcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + CCmaskSHcurve(DEF_MASK_CURVE), + LLmaskSHcurve(DEF_MASK_CURVE), + HHmaskSHcurve(DEF_MASK_CURVE), blendmaskSH(0), radmaskSH(10.0), blurSHde(5), @@ -2474,9 +2474,9 @@ LocallabParams::LocallabSpot::LocallabSpot() : softradiustm(0.0), amount(95.), equiltm(true), - CCmasktmcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35 }, - LLmasktmcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, - HHmasktmcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + CCmasktmcurve(DEF_MASK_CURVE), + LLmasktmcurve(DEF_MASK_CURVE), + HHmasktmcurve(DEF_MASK_CURVE), enatmMask(false), blendmasktm(0), radmasktm(10.0), @@ -2492,13 +2492,13 @@ LocallabParams::LocallabSpot::LocallabSpot() : vart(70.), dehaz(0), sensih(30), - localTgaincurve{(double)FCT_MinMaxCPoints, 0.0, 0.12, 0.35, 0.35, 0.70, 0.50, 0.35, 0.35, 1.00, 0.12, 0.35, 0.35}, + localTgaincurve(DEF_RET_CURVE), inversret(false), equilret(true), softradiusret(0.0), - CCmaskreticurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35 }, - LLmaskreticurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, - HHmaskreticurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + CCmaskreticurve(DEF_MASK_CURVE), + LLmaskreticurve(DEF_MASK_CURVE), + HHmaskreticurve(DEF_MASK_CURVE), enaretiMask(false), enaretiMasktmap(false), blendmaskreti(0), @@ -2532,7 +2532,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : sensilc(19), fftwlc(false), localcontMethod("loc"), - locwavcurve{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}, + locwavcurve(DEF_LC_CURVE), // Contrast by detail levels expcbdl(false), mult{1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, @@ -2544,9 +2544,9 @@ LocallabParams::LocallabSpot::LocallabSpot() : blurcbdl(0.), softradiuscb(0.0), enacbMask(false), - CCmaskcbcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35 }, - LLmaskcbcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, - HHmaskcbcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}, + CCmaskcbcurve(DEF_MASK_CURVE), + LLmaskcbcurve(DEF_MASK_CURVE), + HHmaskcbcurve(DEF_MASK_CURVE), blendmaskcb(0), radmaskcb(10.0), chromaskcb(0.0), @@ -2822,6 +2822,12 @@ bool LocallabParams::LocallabSpot::operator !=(const LocallabSpot& other) const const double LocallabParams::LABGRIDL_CORR_MAX = 12800.; const double LocallabParams::LABGRIDL_CORR_SCALE = 3.276; const double LocallabParams::LABGRIDL_DIRECT_SCALE = 41950.; +const std::vector LocallabParams::DEF_MASK_CURVE = {(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.0, 1.0, 0.35, 0.35}; +const std::vector LocallabParams::DEF_COLOR_LCURVE = {(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}; +const std::vector LocallabParams::DEF_COLOR_HCURVE = {(double)FCT_MinMaxCPoints, 0.0, 0.50, 0.35, 0.35, 0.166, 0.50, 0.35, 0.35, 0.333, 0.50, 0.35, 0.35, 0.50, 0.50, 0.35, 0.35, 0.666, 0.50, 0.35, 0.35, 0.833, 0.50, 0.35, 0.35}; +const std::vector LocallabParams::DEF_EXP_CURVE = {(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}; +const std::vector LocallabParams::DEF_RET_CURVE = {(double)FCT_MinMaxCPoints, 0.0, 0.12, 0.35, 0.35, 0.70, 0.50, 0.35, 0.35, 1.00, 0.12, 0.35, 0.35}; +const std::vector LocallabParams::DEF_LC_CURVE = {(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}; LocallabParams::LocallabParams() : enabled(false), diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 9bb7d4ece..ebc3055b1 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1178,6 +1178,12 @@ struct LocallabParams { static const double LABGRIDL_CORR_MAX; static const double LABGRIDL_CORR_SCALE; static const double LABGRIDL_DIRECT_SCALE; + static const std::vector DEF_MASK_CURVE; + static const std::vector DEF_COLOR_LCURVE; + static const std::vector DEF_COLOR_HCURVE; + static const std::vector DEF_EXP_CURVE; + static const std::vector DEF_RET_CURVE; + static const std::vector DEF_LC_CURVE; int nbspot; int selspot; std::vector spots; diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index cc2f3eae8..85884ab78 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -93,6 +93,8 @@ set(NONCLISOURCEFILES lensprofile.cc localcontrast.cc locallab.cc + locallabtools.cc + locallabtools2.cc lockablecolorpicker.cc lwbutton.cc lwbuttonset.cc diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index 2577c970d..9326bc7e1 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -32,6 +32,7 @@ #include #include "../rtengine/improcfun.h" #include "labgrid.h" +#include "locallabtools.h" #define MINCHRO 0. #define MAXCHRO 150 @@ -392,6 +393,10 @@ Locallab::Locallab(): LocallabParams::LocallabSpot defSpot; + // Test + LocallabDenoise* const test = new LocallabDenoise(); + panel->pack_start(*test->getExpander(), false, false); + // Settings expsettings->getExpander()->signal_button_release_event().connect_notify(sigc::bind(sigc::mem_fun(this, &Locallab::foldAllButMe), expsettings->getExpander())); expsettings->setLevel(2); diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc new file mode 100644 index 000000000..3a77be69e --- /dev/null +++ b/rtgui/locallabtools.cc @@ -0,0 +1,2539 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath frame + * + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + * 2019 Pierre Cabrera + */ +#include "locallabtools.h" + +#include "options.h" +#include "multilangmgr.h" +#include "../rtengine/procparams.h" + +using namespace rtengine; +using namespace procparams; + +extern Options options; + +/* ==== LocallabTool ==== */ +LocallabTool::LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11, maskType usemask): + ToolPanel(toolName, need11), + + // LocallabTool parameters + useMask(usemask), + isLocActivated(false), + locToolListener(nullptr) +{ + const bool showtooltip = options.showtooltip; + + // Create expander title bar + Gtk::HBox* const titleBox = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const titleLabel = Gtk::manage(new Gtk::Label()); + titleLabel->set_markup(Glib::ustring("") + escapeHtmlChars(UILabel) + Glib::ustring("")); + titleLabel->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + titleBox->pack_start(*titleLabel, Gtk::PACK_EXPAND_WIDGET, 0); + + Gtk::EventBox* const removeEvBox = Gtk::manage(new Gtk::EventBox()); // Glue to manage mouse clicking event on remove image + removeEvBox->set_can_focus(false); + removeEvBox->set_above_child(false); // To have priority over expander title bar when mouse clicking on remove image + removeEvBox->signal_button_release_event().connect(sigc::mem_fun(this, &LocallabTool::on_remove_change)); + RTImage* const removeImage = Gtk::manage(new RTImage("cancel-small.png")); + removeEvBox->add(*removeImage); + titleBox->pack_end(*removeEvBox, Gtk::PACK_SHRINK, 4); + + if (need100Percent) { + RTImage* titleImage = Gtk::manage(new RTImage("one-to-one-small.png")); + + if (showtooltip) { + titleImage->set_tooltip_text(M("TP_GENERAL_11SCALE_TOOLTIP")); + } + + titleBox->pack_end(*titleImage, Gtk::PACK_SHRINK, 0); + } + + exp = Gtk::manage(new MyExpander(true, titleBox)); + enaExpConn = exp->signal_enabled_toggled().connect(sigc::mem_fun(*this, &LocallabTool::enabledChanged)); + + ToolParamBlock* const totalBox = Gtk::manage(new ToolParamBlock()); + + // Create panel for specific widget tools + totalBox->pack_start(*content, Gtk::PACK_SHRINK, 0); + + // Create mask panel + if (useMask) { + maskExp = Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_SHOW"))); + setExpandAlignProperties(maskExp, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); + + showMaskMethod = Gtk::manage(new MyComboBoxText()); + showMaskMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showMaskMethod->append(M("TP_LOCALLAB_SHOWMODIF")); + showMaskMethod->append(M("TP_LOCALLAB_SHOWMODIFMASK")); + showMaskMethod->append(M("TP_LOCALLAB_SHOWMASK")); + showMaskMethod->append(M("TP_LOCALLAB_SHOWSTRUC")); + showMaskMethod->append(M("TP_LOCALLAB_PREVIEWSEL")); + showMaskMethod->set_active(0); + + if (showtooltip) { + showMaskMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKCOL_TOOLTIP")); + } + + showMaskMethodConn = showMaskMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabTool::showMaskMethodChanged)); + + enaMask = Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ENABLE_MASK"))); + enaMaskConn = enaMask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabTool::enaMaskChanged)); + + if (useMask == MaskWithTrMap) { + enaMaskTrMap = Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_TM_MASK"))); + enaMaskTrMapConn = enaMaskTrMap->signal_toggled().connect(sigc::mem_fun(*this, &LocallabTool::enaMaskTrMapChanged)); + } + + maskCurveEditorG = new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_MASK")); + maskCurveEditorG->setCurveListener(this); + + CCMaskShape = static_cast(maskCurveEditorG->addCurve(CT_Flat, "C(C)", nullptr, false, false)); + CCMaskShape->setIdentityValue(0.); + CCMaskShape->setResetCurve(FlatCurveType(LocallabParams::DEF_MASK_CURVE.at(0)), LocallabParams::DEF_MASK_CURVE); + + if (showtooltip) { + CCMaskShape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + CCMaskShape->setBottomBarColorProvider(this, 1); + + std::vector bgGradient; + bgGradient.push_back(GradientMilestone(0., 0., 0., 0.)); + bgGradient.push_back(GradientMilestone(1., 1., 1., 1.)); + LLMaskShape = static_cast(maskCurveEditorG->addCurve(CT_Flat, "L(L)", nullptr, false, false)); + LLMaskShape->setIdentityValue(0.); + LLMaskShape->setResetCurve(FlatCurveType(LocallabParams::DEF_MASK_CURVE.at(0)), LocallabParams::DEF_MASK_CURVE); + + if (showtooltip) { + LLMaskShape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + LLMaskShape->setBottomBarBgGradient(bgGradient); + + HHMaskShape = static_cast(maskCurveEditorG->addCurve(CT_Flat, "LC(H)", nullptr, false, true)); + HHMaskShape->setIdentityValue(0.); + HHMaskShape->setResetCurve(FlatCurveType(LocallabParams::DEF_MASK_CURVE.at(0)), LocallabParams::DEF_MASK_CURVE); + + if (showtooltip) { + HHMaskShape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_CC_TOOLTIP")); + } + + HHMaskShape->setCurveColorProvider(this, 2); + HHMaskShape->setBottomBarColorProvider(this, 2); + + maskCurveEditorG->curveListComplete(); + + blendMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLENDMASKCOL"), -100, 100, 1, 0)); + blendMask->setAdjusterListener(this); + + radMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADMASKCOL"), 0.0, 100.0, 0.1, 10.)); + radMask->setAdjusterListener(this); + + chroMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMASKCOL"), -100.0, 100.0, 0.1, 0.)); + chroMask->setAdjusterListener(this); + + gamMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAMMASKCOL"), 0.25, 4.0, 0.01, 1.)); + gamMask->setAdjusterListener(this); + + sloMask = Gtk::manage(new Adjuster(M("TP_LOCALLAB_SLOMASKCOL"), 0.0, 15.0, 0.1, 0.)); + sloMask->setAdjusterListener(this); + + ToolParamBlock* const maskBox = Gtk::manage(new ToolParamBlock()); + maskBox->pack_start(*showMaskMethod, Gtk::PACK_SHRINK, 4); + maskBox->pack_start(*enaMask, Gtk::PACK_SHRINK, 0); + + if (useMask == MaskWithTrMap) { + maskBox->pack_start(*enaMaskTrMap, Gtk::PACK_SHRINK, 0); + } + + maskBox->pack_start(*maskCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + maskBox->pack_start(*blendMask, Gtk::PACK_SHRINK, 0); + maskBox->pack_start(*radMask, Gtk::PACK_SHRINK, 0); + maskBox->pack_start(*chroMask, Gtk::PACK_SHRINK, 0); + maskBox->pack_start(*gamMask, Gtk::PACK_SHRINK, 0); + maskBox->pack_start(*sloMask, Gtk::PACK_SHRINK, 0); + maskExp->add(*maskBox, false); + totalBox->pack_start(*maskExp, Gtk::PACK_SHRINK, 0); + } + + exp->add(*totalBox, false); + exp->setLevel(2); +} + +LocallabTool::~LocallabTool() +{ + idle_register.destroy(); + + if (useMask) { + delete maskCurveEditorG; + } +} + +void LocallabTool::addLocallabTool(bool cond) +{ + exp->set_visible(cond); +} + +bool LocallabTool::isLocallabToolAdded() +{ + return exp->get_visible(); +} + +void LocallabTool::resetMaskView() +{ + if (useMask) { + showMaskMethodConn.block(true); + showMaskMethod->set_active(0); + showMaskMethodConn.block(false); + } +} + +void LocallabTool::refChanged(double huer, double lumar, double chromar) +{ + // Hue reference normalization (between 0 and 1) + double normHuer = huer; + float h = Color::huelab_to_huehsv2(normHuer); + h += 1.f / 6.f; + + if (h > 1.f) { + h -= 1.f; + } + + normHuer = h; + + // Luma reference normalization (between 0 and 1) + const double normLumar = lumar / 100.f; + + // Chroma reference normalization (between 0 and 1) + const double normChromar = chromar / 137.4f; + + // printf("nh=%f nl=%f nc=%f\n", normHuer, normLumar, normChromar); + + idle_register.add( + [this, normHuer, normLumar, normChromar]() -> bool { + GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected + + // Update mask background + CCMaskShape->updateLocallabBackground(normChromar); + LLMaskShape->updateLocallabBackground(normLumar); + HHMaskShape->updateLocallabBackground(normHuer); + + return false; + } + ); +} + +void LocallabTool::colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) +{ + if (useMask) { + float R = 0.f; + float G = 0.f; + float B = 0.f; + + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5; + } + + switch (callerId) { + case 1: // CCmaskshape + Color::hsv2rgb01(float(valY), float(valX), 0.5f, R, G, B); + + break; + + case 2: // HHmaskshape + // TODO + float x = valX - 1.f / 6.f; + + if (x < 0.f) { + x += 1.f; + } + + x = log2lin(x, 3.f); + // float x = valX; + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + } + + caller->ccRed = double (R); + caller->ccGreen = double (G); + caller->ccBlue = double (B); + } +} + +void LocallabTool::disableListener() +{ + ToolPanel::disableListener(); + + enaExpConn.block(true); + + if (useMask) { + enaMaskConn.block(true); + + if (useMask == MaskWithTrMap) { + enaMaskTrMapConn.block(true); + } + + showMaskMethodConn.block(true); + } +} +void LocallabTool::enableListener() +{ + ToolPanel::enableListener(); + + enaExpConn.block(false); + + if (useMask) { + enaMaskConn.block(false); + + if (useMask == MaskWithTrMap) { + enaMaskTrMapConn.block(false); + } + + showMaskMethodConn.block(false); + } +} + +bool LocallabTool::on_remove_change(GdkEventButton* event) +{ + if (event->button == GDK_BUTTON_PRIMARY) { + printf("Remove icon pressed\n"); + // exp->set_visible(false); + } + + return true; // No event propagation further (to avoid closing expander when mouse clicking on remove image) +} + +/* ==== LocallabColor ==== */ +LocallabColor::LocallabColor(): + LocallabTool(this, "Locallab Color&Light", M("TP_LOCALLAB_COFR"), false, MaskNormal), + + // Color & Light specific widgets + curvactiv(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_CURV")))), + lightness(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LIGHTNESS"), -100, 100, 1, 0))), + contrast(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTRAST"), -100, 100, 1, 0))), + chroma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMA"), -100, 150, 1, 0))), + gridFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_LABGRID")))), + labgrid(Gtk::manage(new LabGrid(EvLocallabLabGridValue, M("TP_LOCALLAB_LABGRID_VALUES")))), + gridMethod(Gtk::manage(new MyComboBoxText())), + strengthgrid(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRGRID"), 0, 100, 1, 30))), + sensi(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), + structcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUCCOL"), 0, 100, 1, 0))), + blurcolde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))), + softradiuscol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))), + labqualcurv(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_QUALCURV_METHOD") + ":"))), + qualitycurveMethod(Gtk::manage(new MyComboBoxText())), + llCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_LUM"))), + HCurveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_HLH"))), + invers(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) +{ + float R, G, B; + + const bool showtooltip = options.showtooltip; + + curvactivConn = curvactiv->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::curvactivChanged)); + + lightness->setAdjusterListener(this); + + if (showtooltip) { + lightness->set_tooltip_text(M("TP_LOCALLAB_EXPCOLOR_TOOLTIP")); + } + + contrast->setAdjusterListener(this); + + chroma->setAdjusterListener(this); + + gridMethod->append(M("TP_LOCALLAB_GRIDONE")); + gridMethod->append(M("TP_LOCALLAB_GRIDTWO")); + gridMethod->set_active(0); + gridMethodConn = gridMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabColor::gridMethodChanged)); + + strengthgrid->setAdjusterListener(this); + + sensi->setAdjusterListener(this); + + if (showtooltip) { + sensi->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + } + + structcol->setAdjusterListener(this); + + blurcolde->setAdjusterListener(this); + + softradiuscol->setAdjusterListener(this); + + qualitycurveMethod->append(M("TP_LOCALLAB_CURVNONE")); + qualitycurveMethod->append(M("TP_LOCALLAB_CURVCURR")); + qualitycurveMethod->set_active(0); + + if (showtooltip) { + qualitycurveMethod->set_tooltip_markup(M("TP_LOCALLAB_CURVEMETHOD_TOOLTIP")); + } + + qualitycurveMethodConn = qualitycurveMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabColor::qualitycurveMethodChanged)); + + llCurveEditorG->setCurveListener(this); + llshape = static_cast(llCurveEditorG->addCurve(CT_Diagonal, "L(L)")); + llshape->setResetCurve(DiagonalCurveType(LocallabParams::DEF_COLOR_LCURVE.at(0)), LocallabParams::DEF_COLOR_LCURVE); + + if (showtooltip) { + llshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); + } + + std::vector mllshape; + mllshape.push_back(GradientMilestone(0., 0., 0., 0.)); + mllshape.push_back(GradientMilestone(1., 1., 1., 1.)); + llshape->setBottomBarBgGradient(mllshape); + llshape->setLeftBarBgGradient(mllshape); + + ccshape = static_cast(llCurveEditorG->addCurve(CT_Diagonal, "C(C)")); + ccshape->setResetCurve(DiagonalCurveType(LocallabParams::DEF_COLOR_LCURVE.at(0)), LocallabParams::DEF_COLOR_LCURVE); + + if (showtooltip) { + ccshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); + } + + std::vector mccshape; + mccshape.push_back(GradientMilestone(0., 0., 0., 0.)); + mccshape.push_back(GradientMilestone(1., 1., 1., 1.)); + ccshape->setBottomBarBgGradient(mccshape); + ccshape->setLeftBarBgGradient(mccshape); + + // llCurveEditorG->newLine(); + llCurveEditorG->curveListComplete(); + HCurveEditorG->setCurveListener(this); + + LHshape = static_cast(HCurveEditorG->addCurve(CT_Flat, "L(H)", nullptr, false, true)); + LHshape->setIdentityValue(0.); + LHshape->setResetCurve(FlatCurveType(LocallabParams::DEF_COLOR_HCURVE.at(0)), LocallabParams::DEF_COLOR_HCURVE); + + if (showtooltip) { + LHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); + } + + LHshape->setCurveColorProvider(this, 3); + std::vector mLHshape; + + for (int i = 0; i < 7; i++) { + float x = float (i) * (1.0f / 6.0); + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + mLHshape.push_back(GradientMilestone(double (x), double (R), double (G), double (B))); + } + + LHshape->setBottomBarBgGradient(mLHshape); + + HHshape = static_cast(HCurveEditorG->addCurve(CT_Flat, "H(H)", nullptr, false, true)); + HHshape->setIdentityValue(0.); + HHshape->setResetCurve(FlatCurveType(LocallabParams::DEF_COLOR_HCURVE.at(0)), LocallabParams::DEF_COLOR_HCURVE); + + if (showtooltip) { + HHshape->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_LL_TOOLTIP")); + } + + HHshape->setCurveColorProvider(this, 3); + std::vector mHHshape; + + for (int i = 0; i < 7; i++) { + float x = float (i) * (1.0f / 6.0); + + Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B); + mHHshape.push_back(GradientMilestone(double (x), double (R), double (G), double (B))); + } + + HHshape->setBottomBarBgGradient(mHHshape); + + HCurveEditorG->curveListComplete(); + + inversConn = invers->signal_toggled().connect(sigc::mem_fun(*this, &LocallabColor::inversChanged)); + + Gtk::Frame* const superFrame = Gtk::manage(new Gtk::Frame()); + superFrame->set_label_align(0.025, 0.5); + superFrame->set_label_widget(*curvactiv); + ToolParamBlock* const superBox = Gtk::manage(new ToolParamBlock()); + superBox->pack_start(*lightness); + superBox->pack_start(*contrast); + superBox->pack_start(*chroma); + gridFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const gridBox = Gtk::manage(new ToolParamBlock()); + gridBox->pack_start(*labgrid); + gridBox->pack_start(*gridMethod); + gridBox->pack_start(*strengthgrid); + gridFrame->add(*gridBox); + superBox->pack_start(*gridFrame); + superFrame->add(*superBox); + pack_start(*superFrame); + pack_start(*sensi); + pack_start(*structcol); + pack_start(*blurcolde); + pack_start(*softradiuscol); + Gtk::HBox* const qualcurvbox = Gtk::manage(new Gtk::HBox()); + qualcurvbox->pack_start(*labqualcurv, Gtk::PACK_SHRINK, 4); + qualcurvbox->pack_start(*qualitycurveMethod); + pack_start(*qualcurvbox); + pack_start(*llCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + pack_start(*HCurveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + pack_start(*invers); +} + +LocallabColor::~LocallabColor() +{ + delete llCurveEditorG; + delete HCurveEditorG; +} + +void LocallabColor::colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller) +{ + LocallabTool::colorForValue(valX, valY, elemType, callerId, caller); // Mask curves + + float R = 0.f; + float G = 0.f; + float B = 0.f; + + if (elemType == ColorCaller::CCET_VERTICAL_BAR) { + valY = 0.5; + } + + if (callerId == 3) { // LHshape and HHshape curves + Color::hsv2rgb01(float (valX), float (valY), 0.5f, R, G, B); + + caller->ccRed = double (R); + caller->ccGreen = double (G); + caller->ccBlue = double (B); + } +} + +void LocallabColor::setListener(ToolPanelListener* tpl) +{ + LocallabTool::setListener(tpl); //TODO Check if working + + labgrid->setListener(tpl); +} + +void LocallabColor::disableListener() +{ + LocallabTool::disableListener(); + + curvactivConn.block(true); + gridMethodConn.block(true); + qualitycurveMethodConn.block(true); + inversConn.block(true); +} + +void LocallabColor::enableListener() +{ + LocallabTool::enableListener(); + + curvactivConn.block(false); + gridMethodConn.block(false); + qualitycurveMethodConn.block(false); + inversConn.block(false); +} + +void LocallabColor::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expcolor); + curvactiv->set_active(pp->locallab.spots.at(index).curvactiv); + lightness->setValue(pp->locallab.spots.at(index).lightness); + contrast->setValue(pp->locallab.spots.at(index).contrast); + chroma->setValue(pp->locallab.spots.at(index).chroma); + labgrid->setParams(pp->locallab.spots.at(index).labgridALow / LocallabParams::LABGRIDL_CORR_MAX, + pp->locallab.spots.at(index).labgridBLow / LocallabParams::LABGRIDL_CORR_MAX, + pp->locallab.spots.at(index).labgridAHigh / LocallabParams::LABGRIDL_CORR_MAX, + pp->locallab.spots.at(index).labgridBHigh / LocallabParams::LABGRIDL_CORR_MAX, + false); + + if (pp->locallab.spots.at(index).gridMethod == "one") { + gridMethod->set_active(0); + } else if (pp->locallab.spots.at(index).gridMethod == "two") { + gridMethod->set_active(1); + } + + strengthgrid->setValue(pp->locallab.spots.at(index).strengthgrid); + sensi->setValue(pp->locallab.spots.at(index).sensi); + structcol->setValue(pp->locallab.spots.at(index).structcol); + blurcolde->setValue(pp->locallab.spots.at(index).blurcolde); + softradiuscol->setValue(pp->locallab.spots.at(index).softradiuscol); + + if (pp->locallab.spots.at(index).qualitycurveMethod == "none") { + qualitycurveMethod->set_active(0); + } else if (pp->locallab.spots.at(index).qualitycurveMethod == "std") { + qualitycurveMethod->set_active(1); + } + + llshape->setCurve(pp->locallab.spots.at(index).llcurve); + ccshape->setCurve(pp->locallab.spots.at(index).cccurve); + LHshape->setCurve(pp->locallab.spots.at(index).LHcurve); + HHshape->setCurve(pp->locallab.spots.at(index).HHcurve); + invers->set_active(pp->locallab.spots.at(index).invers); + enaMask->set_active(pp->locallab.spots.at(index).enaColorMask); + CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskcurve); + LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskcurve); + HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskcurve); + blendMask->setValue(pp->locallab.spots.at(index).blendmaskcol); + radMask->setValue(pp->locallab.spots.at(index).radmaskcol); + chroMask->setValue(pp->locallab.spots.at(index).chromaskcol); + gamMask->setValue(pp->locallab.spots.at(index).gammaskcol); + sloMask->setValue(pp->locallab.spots.at(index).slomaskcol); + } + + // Enable all listeners + enableListener(); + + // Update GUI according to invers button state + updateColorGUI(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabColor::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expcolor = exp->getEnabled(); + pp->locallab.spots.at(index).curvactiv = curvactiv->get_active(); + pp->locallab.spots.at(index).lightness = lightness->getIntValue(); + pp->locallab.spots.at(index).contrast = contrast->getIntValue(); + pp->locallab.spots.at(index).chroma = chroma->getIntValue(); + labgrid->getParams(pp->locallab.spots.at(index).labgridALow, + pp->locallab.spots.at(index).labgridBLow, + pp->locallab.spots.at(index).labgridAHigh, + pp->locallab.spots.at(index).labgridBHigh); + pp->locallab.spots.at(index).labgridALow *= LocallabParams::LABGRIDL_CORR_MAX; + pp->locallab.spots.at(index).labgridAHigh *= LocallabParams::LABGRIDL_CORR_MAX; + pp->locallab.spots.at(index).labgridBLow *= LocallabParams::LABGRIDL_CORR_MAX; + pp->locallab.spots.at(index).labgridBHigh *= LocallabParams::LABGRIDL_CORR_MAX; + + if (gridMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(pp->locallab.selspot).gridMethod = "one"; + } else if (gridMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(pp->locallab.selspot).gridMethod = "two"; + } + + pp->locallab.spots.at(index).strengthgrid = strengthgrid->getIntValue(); + pp->locallab.spots.at(index).sensi = sensi->getIntValue(); + pp->locallab.spots.at(index).structcol = structcol->getIntValue(); + pp->locallab.spots.at(index).blurcolde = blurcolde->getIntValue(); + pp->locallab.spots.at(index).softradiuscol = softradiuscol->getValue(); + + if (qualitycurveMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).qualitycurveMethod = "none"; + } else if (qualitycurveMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).qualitycurveMethod = "std"; + } + + pp->locallab.spots.at(index).llcurve = llshape->getCurve(); + pp->locallab.spots.at(index).cccurve = ccshape->getCurve(); + pp->locallab.spots.at(index).LHcurve = LHshape->getCurve(); + pp->locallab.spots.at(index).HHcurve = HHshape->getCurve(); + pp->locallab.spots.at(index).invers = invers->get_active(); + pp->locallab.spots.at(index).enaColorMask = enaMask->get_active(); + pp->locallab.spots.at(index).CCmaskcurve = CCMaskShape->getCurve(); + pp->locallab.spots.at(index).LLmaskcurve = LLMaskShape->getCurve(); + pp->locallab.spots.at(index).HHmaskcurve = HHMaskShape->getCurve(); + pp->locallab.spots.at(index).blendmaskcol = blendMask->getIntValue(); + pp->locallab.spots.at(index).radmaskcol = radMask->getValue(); + pp->locallab.spots.at(index).chromaskcol = chroMask->getValue(); + pp->locallab.spots.at(index).gammaskcol = gamMask->getValue(); + pp->locallab.spots.at(index).slomaskcol = sloMask->getValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabColor::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabColor::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == lightness) { + if (listener) { + listener->panelChanged(Evlocallablightness, + lightness->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == contrast) { + if (listener) { + listener->panelChanged(Evlocallabcontrast, + contrast->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chroma) { + if (listener) { + listener->panelChanged(Evlocallabchroma, + chroma->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strengthgrid) { + if (listener) { + listener->panelChanged(EvLocallabLabstrengthgrid, + strengthgrid->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensi) { + if (listener) { + listener->panelChanged(Evlocallabsensi, + sensi->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == structcol) { + if (listener) { + listener->panelChanged(Evlocallabstructcol, + structcol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blurcolde) { + if (listener) { + listener->panelChanged(Evlocallabblurcolde, + blurcolde->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == softradiuscol) { + if (listener) { + listener->panelChanged(Evlocallabsoftradiuscol, + softradiuscol->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendMask) { + if (listener) { + listener->panelChanged(Evlocallabblendmaskcol, + blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radMask) { + if (listener) { + listener->panelChanged(Evlocallabradmaskcol, + radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chroMask) { + if (listener) { + listener->panelChanged(Evlocallabchromaskcol, + chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gamMask) { + if (listener) { + listener->panelChanged(Evlocallabgammaskcol, + gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sloMask) { + if (listener) { + listener->panelChanged(Evlocallabslomaskcol, + sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == llshape) { + if (listener) { + listener->panelChanged(Evlocallabllshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == ccshape) { + if (listener) { + listener->panelChanged(Evlocallabccshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LHshape) { + if (listener) { + listener->panelChanged(EvlocallabLHshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHshape) { + if (listener) { + listener->panelChanged(EvlocallabHHshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == CCMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabCCmaskshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabHHmaskshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + } +} + +void LocallabColor::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenacolor, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenacolor, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::enaMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaMask->get_active()) { + listener->panelChanged(EvLocallabEnaColorMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaColorMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::showMaskMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskcolMethod, ""); // TODO Use generic event for mask preview + } +} + +void LocallabColor::curvactivChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (curvactiv->get_active()) { + listener->panelChanged(Evlocallabcurvactiv, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabcurvactiv, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::inversChanged() +{ + updateColorGUI(); // Update GUI according to invers button state + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (invers->get_active()) { + listener->panelChanged(Evlocallabinvers, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabinvers, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabColor::qualitycurveMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabqualitycurveMethod, + qualitycurveMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabColor::gridMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvLocallabgridMethod, + gridMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabColor::updateColorGUI() +{ + if (invers->get_active()) { + sensi->show(); + llCurveEditorG->show(); + HCurveEditorG->hide(); + curvactiv->hide(); + qualitycurveMethod->hide(); + labqualcurv->hide(); + maskExp->hide(); + structcol->hide(); + blurcolde->show(); + gridFrame->hide(); + strengthgrid->hide(); + softradiuscol->hide(); + + } else { + sensi->show(); + llCurveEditorG->show(); + HCurveEditorG->show(); + curvactiv->hide(); + qualitycurveMethod->show(); + labqualcurv->show(); + maskExp->show(); + structcol->show(); + blurcolde->show(); + gridFrame->show(); + softradiuscol->show(); + } +} + +/* ==== LocallabExposure ==== */ +LocallabExposure::LocallabExposure(): + LocallabTool(this, "Locallab Exposure", M("TP_LOCALLAB_EXPOSE"), false, MaskNormal), + + // Exposure specific widgets + expMethod(Gtk::manage(new MyComboBoxText())), + pdeFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_PDEFRA")))), + laplacexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPLACEXP"), 0.0, 100.0, 0.1, 20.))), + linear(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LINEAR"), 0., 1., 0.01, 0.))), + balanexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BALANEXP"), 0.2, 1.2, 0.01, 0.8))), + expcomp(Gtk::manage(new Adjuster(M("TP_EXPOSURE_EXPCOMP"), -2.0, 4.0, 0.05, 0.0))), + hlcompr(Gtk::manage(new Adjuster(M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 500, 1, 0))), + hlcomprthresh(Gtk::manage(new Adjuster(M("TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD"), 0, 100, 1, 0))), + black(Gtk::manage(new Adjuster(M("TP_EXPOSURE_BLACKLEVEL"), -16384, 32768, 50, 0))), + shadex(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHADEX"), 0, 100, 1, 0))), + shcompr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHADEXCOMP"), 0, 100, 1, 50))), + expchroma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_EXPCHROMA"), -50, 100, 1, 30))), + warm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_WARM"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-orange-small.png"))))), + sensiex(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), + structexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUCCOL"), 0, 100, 1, 0))), + blurexpde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))), + softradiusexp(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))), + curveEditorG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_CURVEEDITOR_TONES_LABEL"))), + inversex(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) +{ + const bool showtooltip = options.showtooltip; + + if (showtooltip) { + exp->set_tooltip_text(M("TP_LOCALLAB_EXPOSURE_TOOLTIP")); + } + + expMethod->append(M("TP_LOCALLAB_STD")); + expMethod->append(M("TP_LOCALLAB_PDE")); + expMethod->set_active(0); + expMethodConn = expMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabExposure::expMethodChanged)); + + if (showtooltip) { + expMethod->set_tooltip_text(M("TP_LOCALLAB_EXPMETHOD_TOOLTIP")); + } + + pdeFrame->set_label_align(0.025, 0.5); + + laplacexp->setAdjusterListener(this); + + linear->setAdjusterListener(this); + + balanexp->setAdjusterListener(this); + + expcomp->setAdjusterListener(this); + + hlcompr->setAdjusterListener(this); + + hlcomprthresh->setAdjusterListener(this); + + black->setAdjusterListener(this); + + shadex->setAdjusterListener(this); + + shcompr->setAdjusterListener(this); + + expchroma->setAdjusterListener(this); + + if (showtooltip) { + warm->set_tooltip_text(M("TP_LOCALLAB_WARM_TOOLTIP")); + } + + warm->setAdjusterListener(this); + + if (showtooltip) { + sensiex->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + } + + sensiex->setAdjusterListener(this); + + structexp->setAdjusterListener(this); + + blurexpde->setAdjusterListener(this); + + softradiusexp->setAdjusterListener(this); + + curveEditorG->setCurveListener(this); + + shapeexpos = static_cast(curveEditorG->addCurve(CT_Diagonal, "")); + shapeexpos->setResetCurve(DiagonalCurveType(LocallabParams::DEF_EXP_CURVE.at(0)), LocallabParams::DEF_EXP_CURVE); + + if (showtooltip) { + shapeexpos->setTooltip(M("TP_LOCALLAB_CURVEEDITOR_TONES_TOOLTIP")); + } + + std::vector mshapeexpos; + mshapeexpos.push_back(GradientMilestone(0., 0., 0., 0.)); + mshapeexpos.push_back(GradientMilestone(1., 1., 1., 1.)); + shapeexpos->setBottomBarBgGradient(mshapeexpos); + shapeexpos->setLeftBarBgGradient(mshapeexpos); + + curveEditorG->curveListComplete(); + + inversexConn = inversex->signal_toggled().connect(sigc::mem_fun(*this, &LocallabExposure::inversexChanged)); + + pack_start(*expMethod); + ToolParamBlock* const pdeBox = Gtk::manage(new ToolParamBlock()); + pdeBox->pack_start(*laplacexp); + pdeBox->pack_start(*linear); + pdeBox->pack_start(*balanexp); + pdeFrame->add(*pdeBox); + pack_start(*pdeFrame); + pack_start(*expcomp); + pack_start(*hlcompr); + pack_start(*hlcomprthresh); + pack_start(*black); + pack_start(*shadex); + pack_start(*shcompr); + pack_start(*expchroma); + pack_start(*warm); + pack_start(*sensiex); + pack_start(*structexp); + pack_start(*blurexpde); + pack_start(*softradiusexp); + pack_start(*curveEditorG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + pack_start(*inversex); +} + +LocallabExposure::~LocallabExposure() +{ + delete curveEditorG; +} + +void LocallabExposure::disableListener() +{ + LocallabTool::disableListener(); + + expMethodConn.block(true); + inversexConn.block(true); +} + +void LocallabExposure::enableListener() +{ + LocallabTool::enableListener(); + + expMethodConn.block(false); + inversexConn.block(false); +} + +void LocallabExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expexpose); + + if (pp->locallab.spots.at(index).expMethod == "std") { + expMethod->set_active(0); + } else if (pp->locallab.spots.at(index).expMethod == "pde") { + expMethod->set_active(1); + } + + laplacexp->setValue(pp->locallab.spots.at(index).laplacexp); + linear->setValue(pp->locallab.spots.at(index).linear); + balanexp->setValue(pp->locallab.spots.at(index).balanexp); + expcomp->setValue(pp->locallab.spots.at(index).expcomp); + hlcompr->setValue(pp->locallab.spots.at(index).hlcompr); + hlcomprthresh->setValue(pp->locallab.spots.at(index).hlcomprthresh); + black->setValue(pp->locallab.spots.at(index).black); + shadex->setValue(pp->locallab.spots.at(index).shadex); + shcompr->setValue(pp->locallab.spots.at(index).shcompr); + expchroma->setValue(pp->locallab.spots.at(index).expchroma); + warm->setValue(pp->locallab.spots.at(index).warm); + sensiex->setValue(pp->locallab.spots.at(index).sensiex); + structexp->setValue(pp->locallab.spots.at(index).structexp); + blurexpde->setValue(pp->locallab.spots.at(index).blurexpde); + shapeexpos->setCurve(pp->locallab.spots.at(index).excurve); + softradiusexp->setValue(pp->locallab.spots.at(index).softradiusexp); + inversex->set_active(pp->locallab.spots.at(index).inversex); + enaMask->set_active(pp->locallab.spots.at(index).enaExpMask); + CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskexpcurve); + LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskexpcurve); + HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskexpcurve); + blendMask->setValue(pp->locallab.spots.at(index).blendmaskexp); + radMask->setValue(pp->locallab.spots.at(index).radmaskexp); + chroMask->setValue(pp->locallab.spots.at(index).chromaskexp); + gamMask->setValue(pp->locallab.spots.at(index).gammaskexp); + sloMask->setValue(pp->locallab.spots.at(index).slomaskexp); + } + + // Enable all listeners + enableListener(); + + // Update shcompr sensitivity according to black and shadex value + updateExposureGUI1(); + + // Update exposure GUI according to expMethod value + updateExposureGUI2(); + + // Update exposure GUI according to inversex button state + updateExposureGUI3(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabExposure::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expexpose = exp->getEnabled(); + + if (expMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).expMethod = "std"; + } else if (expMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).expMethod = "pde"; + } + + pp->locallab.spots.at(index).laplacexp = laplacexp->getValue(); + pp->locallab.spots.at(index).linear = linear->getValue(); + pp->locallab.spots.at(index).balanexp = balanexp->getValue(); + pp->locallab.spots.at(index).expcomp = expcomp->getValue(); + pp->locallab.spots.at(index).hlcompr = hlcompr->getIntValue(); + pp->locallab.spots.at(index).hlcomprthresh = hlcomprthresh->getIntValue(); + pp->locallab.spots.at(index).black = black->getIntValue(); + pp->locallab.spots.at(index).shadex = shadex->getIntValue(); + pp->locallab.spots.at(index).shcompr = shcompr->getIntValue(); + pp->locallab.spots.at(index).expchroma = expchroma->getIntValue(); + pp->locallab.spots.at(index).warm = warm->getIntValue(); + pp->locallab.spots.at(index).sensiex = sensiex->getIntValue(); + pp->locallab.spots.at(index).structexp = structexp->getIntValue(); + pp->locallab.spots.at(index).blurexpde = blurexpde->getIntValue(); + pp->locallab.spots.at(index).softradiusexp = softradiusexp->getValue(); + pp->locallab.spots.at(index).excurve = shapeexpos->getCurve(); + pp->locallab.spots.at(index).inversex = inversex->get_active(); + pp->locallab.spots.at(index).enaExpMask = enaMask->get_active(); + pp->locallab.spots.at(index).LLmaskexpcurve = LLMaskShape->getCurve(); + pp->locallab.spots.at(index).CCmaskexpcurve = CCMaskShape->getCurve(); + pp->locallab.spots.at(index).HHmaskexpcurve = HHMaskShape->getCurve(); + pp->locallab.spots.at(index).blendmaskexp = blendMask->getIntValue(); + pp->locallab.spots.at(index).radmaskexp = radMask->getValue(); + pp->locallab.spots.at(index).chromaskexp = chroMask->getValue(); + pp->locallab.spots.at(index).gammaskexp = gamMask->getValue(); + pp->locallab.spots.at(index).slomaskexp = sloMask->getValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabExposure::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabExposure::adjusterChanged(Adjuster* a, double newval) +{ + // Update shcompr sensitivity according to black and shadex value + if (a == black || a == shadex) { + updateExposureGUI1(); + } + + if (isLocActivated && exp->getEnabled()) { + if (a == laplacexp) { + if (listener) { + listener->panelChanged(Evlocallablaplacexp, + laplacexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == linear) { + if (listener) { + listener->panelChanged(Evlocallablinear, + linear->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == balanexp) { + if (listener) { + listener->panelChanged(Evlocallabbalanexp, + balanexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == expcomp) { + if (listener) { + listener->panelChanged(Evlocallabexpcomp, + expcomp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == hlcompr) { + if (listener) { + listener->panelChanged(Evlocallabhlcompr, + hlcompr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == hlcomprthresh) { + if (listener) { + listener->panelChanged(Evlocallabhlcomprthresh, + hlcomprthresh->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == black) { + if (listener) { + listener->panelChanged(Evlocallabblack, + black->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shadex) { + if (listener) { + listener->panelChanged(Evlocallabshadex, + shadex->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shcompr) { + if (listener) { + listener->panelChanged(Evlocallabshcompr, + shcompr->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == expchroma) { + if (listener) { + listener->panelChanged(Evlocallabexpchroma, + expchroma->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == warm) { + if (listener) { + listener->panelChanged(Evlocallabwarm, + warm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensiex) { + if (listener) { + listener->panelChanged(Evlocallabsensiex, + sensiex->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == structexp) { + if (listener) { + listener->panelChanged(Evlocallabstructexp, + structexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blurexpde) { + if (listener) { + listener->panelChanged(Evlocallabblurexpde, + blurexpde->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == softradiusexp) { + if (listener) { + listener->panelChanged(Evlocallabsoftradiusexp, + softradiusexp->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendMask) { + if (listener) { + listener->panelChanged(Evlocallabblendmaskexp, + blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radMask) { + if (listener) { + listener->panelChanged(Evlocallabradmaskexp, + radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chroMask) { + if (listener) { + listener->panelChanged(Evlocallabchromaskexp, + chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gamMask) { + if (listener) { + listener->panelChanged(Evlocallabgammaskexp, + gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sloMask) { + if (listener) { + listener->panelChanged(Evlocallabslomaskexp, + sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabExposure::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == shapeexpos) { + if (listener) { + listener->panelChanged(Evlocallabshapeexpos, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == CCMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabCCmaskexpshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskexpshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabHHmaskexpshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabExposure::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenaexpose, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenaexpose, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabExposure::enaMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaMask->get_active()) { + listener->panelChanged(EvLocallabEnaExpMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaExpMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabExposure::showMaskMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskexpMethod, ""); // TODO Use generic event for mask preview + } +} + +void LocallabExposure::expMethodChanged() +{ + // Update exposure GUI according to expMethod value + updateExposureGUI2(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabexpMethod, + expMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabExposure::inversexChanged() +{ + // Update exposure GUI according to inversex button state + updateExposureGUI3(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (inversex->get_active()) { + listener->panelChanged(Evlocallabinversex, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabinversex, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabExposure::updateExposureGUI1() +{ + // Update shcompr sensitivity according to black and shadex value + if (black->getIntValue() == 0 && shadex->getIntValue() == 0) { + shcompr->set_sensitive(false); + } else { + shcompr->set_sensitive(true); + } +} + +void LocallabExposure::updateExposureGUI2() +{ + // Update exposure GUI according to expMethod value + if (expMethod->get_active_row_number() == 0) { + pdeFrame->set_sensitive(false); + laplacexp->set_sensitive(false); + balanexp->set_sensitive(false); + linear->set_sensitive(false); + } else if (expMethod->get_active_row_number() == 1) { + pdeFrame->set_sensitive(true); + laplacexp->set_sensitive(true); + balanexp->set_sensitive(true); + linear->set_sensitive(true); + } +} + +void LocallabExposure::updateExposureGUI3() +{ + // Update exposure GUI according to inversex button state + if (inversex->get_active()) { + maskExp->hide(); + structexp->hide(); + softradiusexp->hide(); + shadex->hide(); + expMethod->hide(); + pdeFrame->hide(); + } else { + maskExp->show(); + structexp->show(); + softradiusexp->show(); + shadex->show(); + expMethod->show(); + pdeFrame->show(); + } +} + +/* ==== LocallabShadow ==== */ +LocallabShadow::LocallabShadow(): + LocallabTool(this, "Locallab Shadows Highlight", M("TP_LOCALLAB_SHADHIGH"), false, MaskNormal), + + // Shadow highlight specific widgets + highlights(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_HIGHLIGHTS"), 0, 100, 1, 0))), + h_tonalwidth(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_HLTONALW"), 10, 100, 1, 70))), + shadows(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_SHADOWS"), 0, 100, 1, 0))), + s_tonalwidth(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_SHTONALW"), 10, 100, 1, 30))), + sh_radius(Gtk::manage(new Adjuster(M("TP_SHADOWSHLIGHTS_RADIUS"), 0, 100, 1, 40))), + sensihs(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), + blurSHde(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURDE"), 2, 100, 1, 5))), + inverssh(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) +{ + const bool showtooltip = options.showtooltip; + + if (showtooltip) { + exp->set_tooltip_text(M("TP_LOCALLAB_SHADOWHIGHLIGHT_TOOLTIP")); + } + + highlights->setAdjusterListener(this); + + h_tonalwidth->setAdjusterListener(this); + + shadows->setAdjusterListener(this); + + s_tonalwidth->setAdjusterListener(this); + + sh_radius->setAdjusterListener(this); + + sensihs->setAdjusterListener(this); + + blurSHde->setAdjusterListener(this); + + inversshConn = inverssh->signal_toggled().connect(sigc::mem_fun(*this, &LocallabShadow::inversshChanged)); + + pack_start(*highlights); + pack_start(*h_tonalwidth); + pack_start(*shadows); + pack_start(*s_tonalwidth); + pack_start(*sh_radius); + pack_start(*sensihs); + pack_start(*blurSHde); + pack_start(*inverssh); +} + +void LocallabShadow::disableListener() +{ + LocallabTool::disableListener(); + + inversshConn.block(true); +} + +void LocallabShadow::enableListener() +{ + LocallabTool::enableListener(); + + inversshConn.block(true); +} + +void LocallabShadow::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expshadhigh); + highlights->setValue(pp->locallab.spots.at(index).highlights); + h_tonalwidth->setValue(pp->locallab.spots.at(index).h_tonalwidth); + shadows->setValue(pp->locallab.spots.at(index).shadows); + s_tonalwidth->setValue(pp->locallab.spots.at(index).s_tonalwidth); + sh_radius->setValue(pp->locallab.spots.at(index).sh_radius); + sensihs->setValue(pp->locallab.spots.at(index).sensihs); + blurSHde->setValue(pp->locallab.spots.at(index).blurSHde); + inverssh->set_active(pp->locallab.spots.at(index).inverssh); + enaMask->set_active(pp->locallab.spots.at(index).enaSHMask); + CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskSHcurve); + LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskSHcurve); + HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskSHcurve); + blendMask->setValue(pp->locallab.spots.at(index).blendmaskSH); + radMask->setValue(pp->locallab.spots.at(index).radmaskSH); + chroMask->setValue(pp->locallab.spots.at(index).chromaskSH); + gamMask->setValue(pp->locallab.spots.at(index).gammaskSH); + sloMask->setValue(pp->locallab.spots.at(index).slomaskSH); + } + + // Enable all listeners + enableListener(); + + // Update shadow highlight GUI according to inverssh button state + updateShadowGUI(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabShadow::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expshadhigh = exp->getEnabled(); + pp->locallab.spots.at(index).highlights = highlights->getIntValue(); + pp->locallab.spots.at(index).h_tonalwidth = h_tonalwidth->getIntValue(); + pp->locallab.spots.at(index).shadows = shadows->getIntValue(); + pp->locallab.spots.at(index).s_tonalwidth = s_tonalwidth->getIntValue(); + pp->locallab.spots.at(index).sh_radius = sh_radius->getIntValue(); + pp->locallab.spots.at(index).sensihs = sensihs->getIntValue(); + pp->locallab.spots.at(index).blurSHde = blurSHde->getIntValue(); + pp->locallab.spots.at(index).inverssh = inverssh->get_active(); + pp->locallab.spots.at(index).enaSHMask = enaMask->get_active(); + pp->locallab.spots.at(index).LLmaskSHcurve = LLMaskShape->getCurve(); + pp->locallab.spots.at(index).CCmaskSHcurve = CCMaskShape->getCurve(); + pp->locallab.spots.at(index).HHmaskSHcurve = HHMaskShape->getCurve(); + pp->locallab.spots.at(index).blendmaskSH = blendMask->getIntValue(); + pp->locallab.spots.at(index).radmaskSH = radMask->getValue(); + pp->locallab.spots.at(index).chromaskSH = chroMask->getValue(); + pp->locallab.spots.at(index).gammaskSH = gamMask->getValue(); + pp->locallab.spots.at(index).slomaskSH = sloMask->getValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabShadow::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabShadow::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == highlights) { + if (listener) { + listener->panelChanged(Evlocallabhighlights, + highlights->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == h_tonalwidth) { + if (listener) { + listener->panelChanged(Evlocallabh_tonalwidth, + h_tonalwidth->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shadows) { + if (listener) { + listener->panelChanged(Evlocallabshadows, + shadows->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == s_tonalwidth) { + if (listener) { + listener->panelChanged(Evlocallabs_tonalwidth, + s_tonalwidth->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sh_radius) { + if (listener) { + listener->panelChanged(Evlocallabsh_radius, + sh_radius->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensihs) { + if (listener) { + listener->panelChanged(Evlocallabsensihs, + sensihs->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blurSHde) { + if (listener) { + listener->panelChanged(EvlocallabblurSHde, + blurSHde->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendMask) { + if (listener) { + listener->panelChanged(EvlocallabblendmaskSH, + blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radMask) { + if (listener) { + listener->panelChanged(EvlocallabradmaskSH, + radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chroMask) { + if (listener) { + listener->panelChanged(EvlocallabchromaskSH, + chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gamMask) { + if (listener) { + listener->panelChanged(EvlocallabgammaskSH, + gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sloMask) { + if (listener) { + listener->panelChanged(EvlocallabslomaskSH, + sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabShadow::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == CCMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabCCmaskSHshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskSHshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabHHmaskSHshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabShadow::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenashadhigh, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenashadhigh, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabShadow::enaMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaMask->get_active()) { + listener->panelChanged(EvLocallabEnaSHMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaSHMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabShadow::showMaskMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskSHMethod, ""); // TODO Use generic event for mask preview + } +} + +void LocallabShadow::inversshChanged() +{ + // Update shadow highlight GUI according to inverssh button state + updateShadowGUI(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (inverssh->get_active()) { + listener->panelChanged(Evlocallabinverssh, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabinverssh, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabShadow::updateShadowGUI() +{ + // Update shadow highlight GUI according to inverssh button state + if (inverssh->get_active()) { + maskExp->hide(); + } else { + maskExp->show(); + } +} + +/* ==== LocallabVibrance ==== */ +LocallabVibrance::LocallabVibrance(): + LocallabTool(this, "Locallab Vibrance", M("TP_LOCALLAB_VIBRANCE"), false, MaskNone), + + // Vibrance specific widgets + saturated(Gtk::manage(new Adjuster(M("TP_VIBRANCE_SATURATED"), -100., 100., 1., 0.))), + pastels(Gtk::manage(new Adjuster(M("TP_VIBRANCE_PASTELS"), -100., 100., 1., 0.))), + psThreshold(Gtk::manage(new ThresholdAdjuster(M("TP_VIBRANCE_PSTHRESHOLD"), -100., 100., 0., M("TP_VIBRANCE_PSTHRESHOLD_WEIGTHING"), 0, 0., 100., 75., M("TP_VIBRANCE_PSTHRESHOLD_SATTHRESH"), 0, this, false))), + protectSkins(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_PROTECTSKINS")))), + avoidColorShift(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_AVOIDCOLORSHIFT")))), + pastSatTog(Gtk::manage(new Gtk::CheckButton(M("TP_VIBRANCE_PASTSATTOG")))), + sensiv(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))), + curveEditorGG(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_LABEL"))) +{ + float R, G, B; + + const bool showtooltip = options.showtooltip; + + saturated->setAdjusterListener(this); + + pastels->setAdjusterListener(this); + + if (showtooltip) { + psThreshold->set_tooltip_markup(M("TP_VIBRANCE_PSTHRESHOLD_TOOLTIP")); + } + + psThreshold->setAdjusterListener(this); + + pskinsConn = protectSkins->signal_toggled().connect(sigc::mem_fun(*this, &LocallabVibrance::protectskins_toggled)); + + ashiftConn = avoidColorShift->signal_toggled().connect(sigc::mem_fun(*this, &LocallabVibrance::avoidcolorshift_toggled)); + + pastsattogConn = pastSatTog->signal_toggled().connect(sigc::mem_fun(*this, &LocallabVibrance::pastsattog_toggled)); + + sensiv->setAdjusterListener(this); + + curveEditorGG->setCurveListener(this); + + skinTonesCurve = static_cast(curveEditorGG->addCurve(CT_Diagonal, M("TP_VIBRANCE_CURVEEDITOR_SKINTONES"))); + + if (showtooltip) { + skinTonesCurve->setTooltip(M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_TOOLTIP")); + } + + std::vector mskinTonesCurve; + // -0.1 rad < Hue < 1.6 rad + Color::hsv2rgb01(0.92f, 0.45f, 0.6f, R, G, B); + mskinTonesCurve.push_back(GradientMilestone(0.0, double (R), double (G), double (B))); + Color::hsv2rgb01(0.14056f, 0.45f, 0.6f, R, G, B); + mskinTonesCurve.push_back(GradientMilestone(1.0, double (R), double (G), double (B))); + skinTonesCurve->setBottomBarBgGradient(mskinTonesCurve); + skinTonesCurve->setLeftBarBgGradient(mskinTonesCurve); + skinTonesCurve->setRangeLabels( + M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE1"), M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE2"), + M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE3"), M("TP_VIBRANCE_CURVEEDITOR_SKINTONES_RANGE4") + ); + skinTonesCurve->setRangeDefaultMilestones(0.1, 0.4, 0.85); + + curveEditorGG->curveListComplete(); + + pack_start(*saturated, Gtk::PACK_SHRINK, 0); + pack_start(*pastels, Gtk::PACK_SHRINK, 0); + pack_start(*psThreshold, Gtk::PACK_SHRINK, 0); + pack_start(*protectSkins, Gtk::PACK_SHRINK, 0); + pack_start(*avoidColorShift, Gtk::PACK_SHRINK, 0); + pack_start(*pastSatTog, Gtk::PACK_SHRINK, 0); + pack_start(*sensiv, Gtk::PACK_SHRINK, 0); + pack_start(*curveEditorGG, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor +} + +LocallabVibrance::~LocallabVibrance() +{ + delete curveEditorGG; +} + +void LocallabVibrance::disableListener() +{ + LocallabTool::disableListener(); + + pskinsConn.block(true); + ashiftConn.block(true); + pastsattogConn.block(true); +} + +void LocallabVibrance::enableListener() +{ + LocallabTool::enableListener(); + + pskinsConn.block(false); + ashiftConn.block(false); + pastsattogConn.block(false); +} + +void LocallabVibrance::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expvibrance); + saturated->setValue(pp->locallab.spots.at(index).saturated); + pastels->setValue(pp->locallab.spots.at(index).pastels); + psThreshold->setValue(pp->locallab.spots.at(index).psthreshold); + protectSkins->set_active(pp->locallab.spots.at(index).protectskins); + avoidColorShift->set_active(pp->locallab.spots.at(index).avoidcolorshift); + pastSatTog->set_active(pp->locallab.spots.at(index).pastsattog); + sensiv->setValue(pp->locallab.spots.at(index).sensiv); + skinTonesCurve->setCurve(pp->locallab.spots.at(index).skintonescurve); + } + + // Enable all listeners + enableListener(); + + // Update vibrance GUI according to pastsattog button state + updateVibranceGUI(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabVibrance::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expvibrance = exp->getEnabled(); + pp->locallab.spots.at(index).saturated = saturated->getIntValue(); + pp->locallab.spots.at(index).pastels = pastels->getIntValue(); + pp->locallab.spots.at(index).psthreshold = psThreshold->getValue(); + pp->locallab.spots.at(index).protectskins = protectSkins->get_active(); + pp->locallab.spots.at(index).avoidcolorshift = avoidColorShift->get_active(); + pp->locallab.spots.at(index).pastsattog = pastSatTog->get_active(); + pp->locallab.spots.at(index).sensiv = sensiv->getIntValue(); + pp->locallab.spots.at(index).skintonescurve = skinTonesCurve->getCurve(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabVibrance::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabVibrance::adjusterChanged(Adjuster* a, double newval) +{ + // Copy pastels adjuster value to saturated one according to pastSatTog button state + if (a == pastels && pastSatTog->get_active()) { + saturated->setValue(newval); + } + + if (isLocActivated && exp->getEnabled()) { + if (a == saturated && !pastSatTog->get_active()) { + if (listener) { + listener->panelChanged(EvlocallabSaturated, + saturated->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == pastels) { + if (listener) { + listener->panelChanged(EvlocallabPastels, + pastels->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensiv) { + if (listener) { + listener->panelChanged(Evlocallabsensiv, + sensiv->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabVibrance::adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop) +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabPastSatThreshold, + psThreshold->getHistoryString() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +std::vector LocallabVibrance::getCurvePoints(ThresholdSelector* tAdjuster) const +{ + std::vector points; + double threshold, transitionWeighting; + tAdjuster->getPositions(transitionWeighting, threshold); // ( range -100;+100, range 0;+100 ) + transitionWeighting /= 100.; // range -1., +1. + threshold /= 100.; // range 0., +1. + + // Initial point + points.push_back(0.); + points.push_back(0.); + + double p2 = 3.0 * threshold / 4.0; // same one than in ipvibrance.cc + double s0 = threshold + (1.0 - threshold) / 4.0; // same one than in ipvibrance.cc + + // point at the beginning of the first linear transition + points.push_back(p2); + points.push_back(0.); + + // Y value of the chroma mean point, calculated to get a straight line between p2 and s0 + double chromaMean = (threshold / 4.0) / (s0 - p2); + + // move chromaMean up or down depending on transitionWeighting + if (transitionWeighting > 0.0) { + // positive values -> give more weight to Saturated + chromaMean = (1.0 - chromaMean) * transitionWeighting + chromaMean; + } else if (transitionWeighting < 0.0) { + // negative values -> give more weight to Pastels + chromaMean = chromaMean * transitionWeighting + chromaMean; + } + + // point at the location of the Top cursor, at the end of the first linear transition and the beginning of the second one + points.push_back(threshold); + points.push_back(chromaMean); + + if (threshold < 1.0) { + // point at the end of the second linear transition + points.push_back(s0); + points.push_back(1.0); + + // end point + points.push_back(1.0); + points.push_back(1.0); + } + + return points; +} + +void LocallabVibrance::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == skinTonesCurve) { + if (listener) { + listener->panelChanged(EvlocallabSkinTonesCurve, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabVibrance::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenavibrance, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenashadhigh, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabVibrance::protectskins_toggled() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (protectSkins->get_active()) { + listener->panelChanged(EvlocallabProtectSkins, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvlocallabProtectSkins, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabVibrance::avoidcolorshift_toggled() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (avoidColorShift->get_active()) { + listener->panelChanged(EvlocallabAvoidColorShift, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvlocallabAvoidColorShift, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabVibrance::pastsattog_toggled() +{ + // Update vibrance GUI according to pastsattog button state + updateVibranceGUI(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (pastSatTog->get_active()) { + listener->panelChanged(EvlocallabPastSatTog, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvlocallabPastSatTog, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabVibrance::updateVibranceGUI() +{ + // Update vibrance GUI according to pastsattog button state + if (pastSatTog->get_active()) { + // Link both slider, so we set saturated and psThresholds unsensitive + psThreshold->set_sensitive(false); + saturated->set_sensitive(false); + saturated->setValue(pastels->getValue()); // Pastels and Saturated are linked + } else { + // Separate sliders, so we set saturated and psThresholds sensitive again + psThreshold->set_sensitive(true); + saturated->set_sensitive(true); + } +} + +/* ==== LocallabSoft ==== */ +LocallabSoft::LocallabSoft(): + LocallabTool(this, "Locallab Soft Light", M("TP_LOCALLAB_SOFT"), false, MaskNone), + + // Soft light specific widgets + softMethod(Gtk::manage(new MyComboBoxText())), + ctboxsoftmethod(Gtk::manage(new Gtk::HBox())), + showmasksoftMethod(Gtk::manage(new MyComboBoxText())), + streng(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRENG"), 1, 100, 1, 1))), + laplace(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPLACE"), 0., 100., 0.5, 25.))), + sensisf(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 1, 100, 1, 15))) +{ + const bool showtooltip = options.showtooltip; + + softMethod->append(M("TP_LOCALLAB_SOFTM")); + softMethod->append(M("TP_LOCALLAB_RETIM")); + softMethod->set_active(0); + + if (showtooltip) { + softMethod->set_tooltip_markup(M("TP_LOCALLAB_SOFTMETHOD_TOOLTIP")); + } + + softMethodConn = softMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabSoft::softMethodChanged)); + + showmasksoftMethod->append(M("TP_LOCALLAB_SHOWMNONE")); + showmasksoftMethod->append(M("TP_LOCALLAB_SHOWLAPLACE")); + showmasksoftMethod->append(M("TP_LOCALLAB_SHOWFOURIER")); + showmasksoftMethod->append(M("TP_LOCALLAB_SHOWPOISSON")); + showmasksoftMethod->append(M("TP_LOCALLAB_SHOWNORMAL")); + showmasksoftMethod->set_active(0); + + if (showtooltip) { + showmasksoftMethod->set_tooltip_markup(M("TP_LOCALLAB_SHOWMASKSOFT_TOOLTIP")); + } + + showmasksoftMethodConn = showmasksoftMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabSoft::showmasksoftMethodChanged)); + + streng->setAdjusterListener(this); + + laplace->setAdjusterListener(this); + + sensisf->setAdjusterListener(this); + + pack_start(*softMethod); + Gtk::Label* const labelsoftmethod = Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_SHOWDCT") + ":")); + ctboxsoftmethod->pack_start(*labelsoftmethod, Gtk::PACK_SHRINK, 4); + ctboxsoftmethod->pack_start(*showmasksoftMethod); + pack_start(*ctboxsoftmethod); + pack_start(*streng); + pack_start(*laplace); + pack_start(*sensisf); +} + +void LocallabSoft::disableListener() +{ + LocallabTool::disableListener(); + + softMethodConn.block(true); + showmasksoftMethodConn.block(true); +} + +void LocallabSoft::enableListener() +{ + LocallabTool::enableListener(); + + softMethodConn.block(false); + showmasksoftMethodConn.block(false); +} + +void LocallabSoft::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expsoft); + + if (pp->locallab.spots.at(index).softMethod == "soft") { + softMethod->set_active(0); + } else if (pp->locallab.spots.at(index).softMethod == "reti") { + softMethod->set_active(1); + } + + streng->setValue(pp->locallab.spots.at(index).streng); + sensisf->setValue(pp->locallab.spots.at(index).sensisf); + laplace->setValue(pp->locallab.spots.at(index).laplace); + } + + // Enable all listeners + enableListener(); + + // Update soft light GUI according to softMethod combobox + updateSoftGUI(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabSoft::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expsoft = exp->getEnabled(); + + if (softMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).softMethod = "soft"; + } else if (softMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).softMethod = "reti"; + } + + pp->locallab.spots.at(index).streng = streng->getIntValue(); + pp->locallab.spots.at(index).sensisf = sensisf->getIntValue(); + pp->locallab.spots.at(index).laplace = laplace->getValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabSoft::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabSoft::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == streng) { + if (listener) { + listener->panelChanged(Evlocallabstreng, + streng->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensisf) { + if (listener) { + listener->panelChanged(Evlocallabsensisf, + sensisf->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == laplace) { + if (listener) { + listener->panelChanged(Evlocallablaplace, + laplace->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabSoft::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenasoft, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenasoft, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabSoft::softMethodChanged() +{ + // Update soft light GUI according to softMethod combobox + updateSoftGUI(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabsoftMethod, + softMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabSoft::showmasksoftMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmasksoftMethod, ""); // TODO Use generic event for mask preview + } +} + +void LocallabSoft::updateSoftGUI() +{ + // Update soft light GUI according to softMethod combobox + if (softMethod->get_active_row_number() == 0) { + laplace->hide(); + ctboxsoftmethod->hide(); + } else { + laplace->show(); + ctboxsoftmethod->show(); + } +} + +/* ==== LocallabBlur ==== */ +LocallabBlur::LocallabBlur(): + LocallabTool(this, "Locallab Blur & Noise", M("TP_LOCALLAB_BLUFR"), false, MaskNone), + + // Blur & Noise specific widgets + radius(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RADIUS"), 1.0, 100.0, 0.1, 1.0))), + strength(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRENGTH"), 0, 100, 1, 0))), + sensibn(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIBN"), 0, 100, 1, 40))), + blurMethod(Gtk::manage(new MyComboBoxText())), + activlum(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_ACTIV")))) +{ + const bool showtooltip = options.showtooltip; + + radius->setAdjusterListener(this); + + strength->setAdjusterListener(this); + + if (showtooltip) { + sensibn->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); + } + + sensibn->setAdjusterListener(this); + + blurMethod->append(M("TP_LOCALLAB_BLNORM")); + blurMethod->append(M("TP_LOCALLAB_BLINV")); + blurMethod->set_active(0); + + if (showtooltip) { + blurMethod->set_tooltip_markup(M("TP_LOCALLAB_BLMETHOD_TOOLTIP")); + } + + blurMethodConn = blurMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::blurMethodChanged)); + + activlumConn = activlum->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::activlumChanged)); + + pack_start(*radius); + pack_start(*strength); + pack_start(*sensibn); + pack_start(*blurMethod); + pack_start(*activlum); +} + +void LocallabBlur::disableListener() +{ + LocallabTool::disableListener(); + + blurMethodConn.block(true); + activlumConn.block(true); +} + +void LocallabBlur::enableListener() +{ + LocallabTool::enableListener(); + + blurMethodConn.block(false); + activlumConn.block(false); +} + +void LocallabBlur::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expblur); + radius->setValue(pp->locallab.spots.at(index).radius); + strength->setValue(pp->locallab.spots.at(index).strength); + sensibn->setValue(pp->locallab.spots.at(index).sensibn); + + if (pp->locallab.spots.at(index).blurMethod == "norm") { + blurMethod->set_active(0); + } else if (pp->locallab.spots.at(index).blurMethod == "inv") { + blurMethod->set_active(1); + } + + activlum->set_active(pp->locallab.spots.at(index).activlum); + } + + // Enable all listeners + enableListener(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabBlur::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expsoft = exp->getEnabled(); + + pp->locallab.spots.at(index).expblur = exp->getEnabled(); + pp->locallab.spots.at(index).radius = radius->getValue(); + pp->locallab.spots.at(index).strength = strength->getIntValue(); + pp->locallab.spots.at(index).sensibn = sensibn->getIntValue(); + + + if (blurMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).blurMethod = "norm"; + } else if (blurMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).blurMethod = "inv"; + } + + pp->locallab.spots.at(index).activlum = activlum->get_active(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabBlur::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabBlur::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == radius) { + if (listener) { + listener->panelChanged(Evlocallabradius, + radius->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == strength) { + if (listener) { + listener->panelChanged(Evlocallabstrength, + strength->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensibn) { + if (listener) { + listener->panelChanged(Evlocallabsensibn, + sensibn->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabBlur::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenablur, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenablur, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabBlur::blurMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabblurMethod, + blurMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabBlur::activlumChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (activlum->get_active()) { + listener->panelChanged(Evlocallabactivlum, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabactivlum, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} diff --git a/rtgui/locallabtools.h b/rtgui/locallabtools.h new file mode 100644 index 000000000..1d1970fd3 --- /dev/null +++ b/rtgui/locallabtools.h @@ -0,0 +1,654 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath frame + * + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + * 2019 Pierre Cabrera + */ +#ifndef _LOCALLABTOOLS_H_ +#define _LOCALLABTOOLS_H_ + +#include "toolpanel.h" +#include "curveeditorgroup.h" +#include "curveeditor.h" +#include "../rtengine/rtengine.h" +#include "labgrid.h" +#include "thresholdadjuster.h" + +/* ==== LocallabToolListener ==== */ +class LocallabTool; +class LocallabToolListener +{ +public: + LocallabToolListener() {}; + virtual ~LocallabToolListener() {}; + + virtual void resetOtherMaskView(LocallabTool* current) {}; +}; + + +/* ==== LocallabTool ==== */ +class LocallabTool: + public ToolPanel, + public CurveListener, + public ColorProvider, + public AdjusterListener, + public rtengine::LocallabListener +{ +protected: + // Enumeration to manage mask type + enum maskType { + MaskNone = 0, + MaskNormal = 1, + MaskWithTrMap = 2 + }; + + // LocallabTool parameters + const maskType useMask; + bool isLocActivated; + Glib::ustring spotName; + LocallabToolListener* locToolListener; + + // LocallabTool generic widgets + MyExpander* exp; + + // Mask widgets + MyExpander* maskExp; + Gtk::CheckButton* enaMask; + Gtk::CheckButton* enaMaskTrMap; + MyComboBoxText* showMaskMethod; + CurveEditorGroup* maskCurveEditorG; + FlatCurveEditor* CCMaskShape; + FlatCurveEditor* LLMaskShape; + FlatCurveEditor* HHMaskShape; + Adjuster* blendMask; + Adjuster* radMask; + Adjuster* chroMask; + Adjuster* gamMask; + Adjuster* sloMask; + sigc::connection enaExpConn, enaMaskConn, enaMaskTrMapConn, showMaskMethodConn; + +private: + IdleRegister idle_register; + +public: + // Locallab tool constructor/destructor + LocallabTool(Gtk::Box* content, Glib::ustring toolName, Glib::ustring UILabel, bool need11 = false, maskType usemask = MaskNone); + virtual ~LocallabTool(); + + // Getter for Locallab tool expander + MyExpander* getExpander() + { + return exp; + } + + // Setter for Locallab activation indicator + void isLocallabActivated(bool cond) + { + isLocActivated = cond; + } + + // Setter for spot name + void setSpotName(const Glib::ustring &spotname) + { + spotName = spotname; + } + + // Setter for Locallab tool listener + void setLocallabToolListener(LocallabToolListener* ltl) + { + locToolListener = ltl; + } + + // Management functions to add/remove Locallab tool + void addLocallabTool(bool cond); + bool isLocallabToolAdded(); + + // Mask background management function + void refChanged(double huer, double lumar, double chromar); + + // Mask preview reset function + void resetMaskView(); + + /* To be completed + Notes: + - parent class functions shall be called when using mask + - callerId #1 and #2 are reserved for mask curve color management + */ + virtual void colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + + // To be implemented + virtual void disableListener(); + virtual void enableListener(); + virtual void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) {}; + virtual void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) {}; + virtual void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) {}; + virtual void adjusterChanged(Adjuster* a, double newval) {}; // At least when using mask + virtual void curveChanged(CurveEditor* ce) {}; // At least when using mask + +protected: + // To be implemented + virtual void enaMaskChanged() {}; // Only necessary when using mask + virtual void enaMaskTrMapChanged() {}; // Only necessary when using mask with transmission map + virtual void showMaskMethodChanged() {}; // Only necessary when using mask + +private: + // Remove button event function + bool on_remove_change(GdkEventButton* event); + + // To be implemented + virtual void enabledChanged() {}; +}; + +/* ==== LocallabColor ==== */ +class LocallabColor: + public Gtk::VBox, + public LocallabTool +{ +private: + // Color & Light specific widgets + Gtk::CheckButton* const curvactiv; + Adjuster* const lightness; + Adjuster* const contrast; + Adjuster* const chroma; + Gtk::Frame* const gridFrame; + LabGrid* const labgrid; + MyComboBoxText* const gridMethod; + Adjuster* const strengthgrid; + Adjuster* const sensi; + Adjuster* const structcol; + Adjuster* const blurcolde; + Adjuster* const softradiuscol; + Gtk::Label* const labqualcurv; + MyComboBoxText* const qualitycurveMethod; + CurveEditorGroup* const llCurveEditorG; + DiagonalCurveEditor* llshape; + DiagonalCurveEditor* ccshape; + CurveEditorGroup* const HCurveEditorG; + FlatCurveEditor* LHshape; + FlatCurveEditor* HHshape; + Gtk::CheckButton* const invers; + sigc::connection curvactivConn, gridMethodConn, qualitycurveMethodConn, inversConn; + +public: + LocallabColor(); + ~LocallabColor(); + + void setListener(ToolPanelListener* tpl); + + void colorForValue(double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + void curveChanged(CurveEditor* ce); + +private: + void enabledChanged(); + + void enaMaskChanged(); + void showMaskMethodChanged(); + + void curvactivChanged(); + void inversChanged(); + void qualitycurveMethodChanged(); + void gridMethodChanged(); + + void updateColorGUI(); +}; + +/* ==== LocallabExposure ==== */ +class LocallabExposure: + public Gtk::VBox, + public LocallabTool +{ +private: + MyComboBoxText* const expMethod; + Gtk::Frame* const pdeFrame; + Adjuster* const laplacexp; + Adjuster* const linear; + Adjuster* const balanexp; + Adjuster* const expcomp; + Adjuster* const hlcompr; + Adjuster* const hlcomprthresh; + Adjuster* const black; + Adjuster* const shadex; + Adjuster* const shcompr; + Adjuster* const expchroma; + Adjuster* const warm; + Adjuster* const sensiex; + Adjuster* const structexp; + Adjuster* const blurexpde; + Adjuster* const softradiusexp; + CurveEditorGroup* const curveEditorG; + DiagonalCurveEditor* shapeexpos; + Gtk::CheckButton* const inversex; + sigc::connection expMethodConn, inversexConn; + +public: + LocallabExposure(); + ~LocallabExposure(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + void curveChanged(CurveEditor* ce); + +private: + void enabledChanged(); + + void enaMaskChanged(); + void showMaskMethodChanged(); + + void expMethodChanged(); + void inversexChanged(); + + void updateExposureGUI1(); + void updateExposureGUI2(); + void updateExposureGUI3(); +}; + +/* ==== LocallabShadow ==== */ +class LocallabShadow: + public Gtk::VBox, + public LocallabTool +{ +private: + Adjuster* const highlights; + Adjuster* const h_tonalwidth; + Adjuster* const shadows; + Adjuster* const s_tonalwidth; + Adjuster* const sh_radius; + Adjuster* const sensihs; + Adjuster* const blurSHde; + Gtk::CheckButton* const inverssh; + sigc::connection inversshConn; + +public: + LocallabShadow(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + void curveChanged(CurveEditor* ce); + +private: + void enabledChanged(); + + void enaMaskChanged(); + void showMaskMethodChanged(); + + void inversshChanged(); + + void updateShadowGUI(); +}; + +/* ==== LocallabVibrance ==== */ +class LocallabVibrance: + public Gtk::VBox, + public LocallabTool, + public ThresholdAdjusterListener, + public ThresholdCurveProvider +{ +private: + Adjuster* const saturated; + Adjuster* const pastels; + ThresholdAdjuster* const psThreshold; + Gtk::CheckButton* const protectSkins; + Gtk::CheckButton* const avoidColorShift; + Gtk::CheckButton* const pastSatTog; + Adjuster* const sensiv; + CurveEditorGroup* const curveEditorGG; + DiagonalCurveEditor* skinTonesCurve; + sigc::connection pskinsConn, ashiftConn, pastsattogConn; + +public: + LocallabVibrance(); + ~LocallabVibrance(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + void adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) {}; + void adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) {}; + void adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop); + void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) {}; + void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) {}; + std::vector getCurvePoints(ThresholdSelector* tAdjuster) const; + void curveChanged(CurveEditor* ce); + +private: + void enabledChanged(); + + void protectskins_toggled(); + void avoidcolorshift_toggled(); + void pastsattog_toggled(); + + void updateVibranceGUI(); +}; + +/* ==== LocallabSoft ==== */ +class LocallabSoft: + public Gtk::VBox, + public LocallabTool +{ +private: + MyComboBoxText* const softMethod; + Gtk::HBox* const ctboxsoftmethod; + MyComboBoxText* const showmasksoftMethod; + Adjuster* const streng; + Adjuster* const laplace; + Adjuster* const sensisf; + sigc::connection softMethodConn, showmasksoftMethodConn; + +public: + LocallabSoft(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + +private: + void enabledChanged(); + + void softMethodChanged(); + void showmasksoftMethodChanged(); + + void updateSoftGUI(); +}; + +/* ==== LocallabBlur ==== */ +class LocallabBlur: + public Gtk::VBox, + public LocallabTool +{ +private: + Adjuster* const radius; + Adjuster* const strength; + Adjuster* const sensibn; + MyComboBoxText* const blurMethod; + Gtk::CheckButton* const activlum; + sigc::connection blurMethodConn, activlumConn; + +public: + LocallabBlur(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + +private: + void enabledChanged(); + + void blurMethodChanged(); + void activlumChanged(); +}; + +/* ==== LocallabTone ==== */ +class LocallabTone: + public Gtk::VBox, + public LocallabTool +{ +private: + Adjuster* const amount; + Adjuster* const stren; + Gtk::CheckButton* const equiltm; + Adjuster* const gamma; + Adjuster* const satur; + Adjuster* const estop; + Adjuster* const scaltm; + Adjuster* const rewei; + Adjuster* const softradiustm; + Adjuster* const sensitm; + sigc::connection equiltmConn; + +public: + LocallabTone(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + void curveChanged(CurveEditor* ce); + +private: + void enabledChanged(); + + void enaMaskChanged(); + void showMaskMethodChanged(); + + void equiltmChanged(); +}; + +/* ==== LocallabRetinex ==== */ +class LocallabRetinex: + public Gtk::VBox, + public LocallabTool +{ +private: + MyComboBoxText* const retinexMethod; + Gtk::CheckButton* const fftwreti; + Gtk::CheckButton* const equilret; + Adjuster* const str; + Adjuster* const chrrt; + Adjuster* const neigh; + Adjuster* const vart; + Adjuster* const scalereti; + Adjuster* const limd; + Adjuster* const darkness; + Adjuster* const lightnessreti; + Adjuster* const dehaz; + Adjuster* const softradiusret; + Adjuster* const sensih; + CurveEditorGroup* const LocalcurveEditorgainT; + FlatCurveEditor* cTgainshape; + Gtk::CheckButton* const inversret; + sigc::connection retinexMethodConn, fftwretiConn, equilretConn, inversretConn; + +public: + LocallabRetinex(); + ~LocallabRetinex(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + void curveChanged(CurveEditor* ce); + +private: + void enabledChanged(); + + void enaMaskChanged(); + void enaMaskTrMapChanged(); + void showMaskMethodChanged(); + + void retinexMethodChanged(); + void fftwretiChanged(); + void equilretChanged(); + void inversretChanged(); + + void updateRetinexGUI(); + void updateRetinexGUI2(); +}; + +/* ==== LocallabSharp ==== */ +class LocallabSharp: + public Gtk::VBox, + public LocallabTool +{ +private: + Adjuster* const sharcontrast; + Adjuster* const sharradius; + Adjuster* const sharamount; + Adjuster* const shardamping; + Adjuster* const shariter; + Adjuster* const sharblur; + Adjuster* const sensisha; + Gtk::CheckButton* const inverssha; + sigc::connection inversshaConn; + +public: + LocallabSharp(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + +private: + void enabledChanged(); + + void inversshaChanged(); +}; + +/* ==== LocallabContrast ==== */ +class LocallabContrast: + public Gtk::VBox, + public LocallabTool +{ +private: + MyComboBoxText* const localcontMethod; + Adjuster* const lcradius; + Adjuster* const lcamount; + Adjuster* const lcdarkness; + Adjuster* const lclightness; + CurveEditorGroup* const LocalcurveEditorwav; + FlatCurveEditor* wavshape; + Adjuster* const levelwav; + Adjuster* const residcont; + Adjuster* const sensilc; + Gtk::CheckButton* const fftwlc; + sigc::connection localcontMethodConn, fftwlcConn; + +public: + LocallabContrast(); + ~LocallabContrast(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + void curveChanged(CurveEditor* ce); + +private: + void enabledChanged(); + + void localcontMethodChanged(); + void fftwlcChanged(); + + void updateContrastGUI(); +}; + +/* ==== LocallabCBDL ==== */ +class LocallabCBDL: + public Gtk::VBox, + public LocallabTool +{ +private: + Adjuster* multiplier[6]; + Adjuster* const chromacbdl; + Adjuster* const threshold; + Adjuster* const blurcbdl; + Adjuster* const clarityml; + Adjuster* const contresid; + Adjuster* const softradiuscb; + Adjuster* const sensicb; + + Gtk::Button* const lumacontrastMinusButton; + Gtk::Button* const lumaneutralButton; + Gtk::Button* const lumacontrastPlusButton; + sigc::connection lumacontrastMinusPressedConn, lumaneutralPressedConn, lumacontrastPlusPressedConn; + +public: + LocallabCBDL(); + + void disableListener(); + void enableListener(); + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + void curveChanged(CurveEditor* ce); + +private: + void enabledChanged(); + + void enaMaskChanged(); + void showMaskMethodChanged(); + + void lumacontrastMinusPressed(); + void lumaneutralPressed(); + void lumacontrastPlusPressed(); +}; + +/* ==== LocallabDenoise ==== */ +class LocallabDenoise: + public Gtk::VBox, + public LocallabTool +{ +private: + Adjuster* const noiselumf0; + Adjuster* const noiselumf; + Adjuster* const noiselumf2; + Adjuster* const noiselumc; + Adjuster* const noiselumdetail; + Adjuster* const noiselequal; + Adjuster* const noisechrof; + Adjuster* const noisechroc; + Adjuster* const noisechrodetail; + Adjuster* const adjblur; + Adjuster* const bilateral; + Adjuster* const sensiden; + +public: + LocallabDenoise(); + + void read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void adjusterChanged(Adjuster* a, double newval); + +private: + void enabledChanged(); +}; + +#endif diff --git a/rtgui/locallabtools2.cc b/rtgui/locallabtools2.cc new file mode 100644 index 000000000..144a93a0f --- /dev/null +++ b/rtgui/locallabtools2.cc @@ -0,0 +1,2121 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath frame + * + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + * 2019 Pierre Cabrera + */ +#include "locallabtools.h" + +#include "options.h" +#include "multilangmgr.h" +#include "../rtengine/procparams.h" + +#define MINCHRO 0. +#define MAXCHRO 150 +#define MAXCHROCC 100 +#define MINNEIGH 4 +#define MAXNEIGH 5000 +#define CENTERNEIGH 200 + +using namespace rtengine; +using namespace procparams; + +extern Options options; + +static double retiSlider2neigh(double sval) +{ + // Slider range: 0 - 5000 + double neigh; + + if (sval <= 1000) { + // Linear below center-temp + neigh = MINNEIGH + (sval / 1000.0) * (CENTERNEIGH - MINNEIGH); + } else { + const double slope = (double)(CENTERNEIGH - MINNEIGH) / (MAXNEIGH - CENTERNEIGH); + double x = (sval - 1000) / 1000; // x 0..1 + double y = x * slope + (1.0 - slope) * pow(x, 4.0); + neigh = CENTERNEIGH + y * (MAXNEIGH - CENTERNEIGH); + } + + if (neigh < MINNEIGH) { + neigh = MINNEIGH; + } + + if (neigh > MAXNEIGH) { + neigh = MAXNEIGH; + } + + return neigh; +} + +static double retiNeigh2Slider(double neigh) +{ + double sval; + + if (neigh <= CENTERNEIGH) { + sval = ((neigh - MINNEIGH) / (CENTERNEIGH - MINNEIGH)) * 1000.0; + } else { + const double slope = (double)(CENTERNEIGH - MINNEIGH) / (MAXNEIGH - CENTERNEIGH); + const double y = (neigh - CENTERNEIGH) / (MAXNEIGH - CENTERNEIGH); + double x = pow(y, 0.25); // rough guess of x, will be a little lower + double k = 0.1; + bool add = true; + + // The y=f(x) function is a mess to invert, therefore we have this trial-refinement loop instead. + // From tests, worst case is about 20 iterations, i.e. no problem + for (;;) { + double y1 = x * slope + (1.0 - slope) * pow(x, 4.0); + + if (1000 * fabs(y1 - y) < 0.1) { + break; + } + + if (y1 < y) { + if (!add) { + k /= 2; + } + + x += k; + add = true; + } else { + if (add) { + k /= 2; + } + + x -= k; + add = false; + } + } + + sval = 1000.0 + x * 1000.0; + } + + if (sval < 0) { + sval = 0; + } + + if (sval > 5000) { + sval = 5000; + } + + return sval; +} + +/* ==== LocallabTone ==== */ +LocallabTone::LocallabTone(): + LocallabTool(this, "Locallab Tone Mapping", M("TP_LOCALLAB_TM"), true, MaskNormal), + + // Tone mapping specific widgets + amount(Gtk::manage(new Adjuster(M("TP_LOCALLAB_AMOUNT"), 50., 100.0, 0.5, 95.))), + stren(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STREN"), -0.5, 2.0, 0.01, 0.5))), + equiltm(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EQUIL")))), + gamma(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GAM"), 0.4, 4.0, 0.11, 1.0))), + satur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SATUR"), -100., 100., 0.1, 0.))), // By default satur = 0 ==> use Mantiuk value + estop(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ESTOP"), 0.1, 4.0, 0.01, 0.5))), + scaltm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCALTM"), 0.1, 10.0, 0.01, 4.0))), + rewei(Gtk::manage(new Adjuster(M("TP_LOCALLAB_REWEI"), 0, 3, 1, 0))), + softradiustm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))), + sensitm(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSI"), 0, 100, 1, 15))) +{ + const bool showtooltip = options.showtooltip; + + if (showtooltip) { + exp->set_tooltip_text(M("TP_LOCALLAB_TONEMAP_TOOLTIP")); + } + + amount->setAdjusterListener(this); + + stren->setAdjusterListener(this); + + equiltmConn = equiltm->signal_toggled().connect(sigc::mem_fun(*this, &LocallabTone::equiltmChanged)); + + gamma->setAdjusterListener(this); + + satur->setAdjusterListener(this); + + estop->setAdjusterListener(this); + + if (showtooltip) { + estop->set_tooltip_text(M("TP_LOCALLAB_TONEMAPESTOP_TOOLTIP")); + } + + scaltm->setAdjusterListener(this); + + rewei->setAdjusterListener(this); + + if (showtooltip) { + rewei->set_tooltip_text(M("TP_LOCALLAB_TONEMAPESTOP_TOOLTIP")); + } + + softradiustm->setAdjusterListener(this); + + sensitm->setAdjusterListener(this); + + if (showtooltip) { + sensitm->set_tooltip_text(M("TP_LOCALLAB_SENSI_TOOLTIP")); + } + + // pack_start(*amount); // To use if we change transit_shapedetect parameters + pack_start(*stren); + pack_start(*equiltm); + pack_start(*gamma); + pack_start(*satur); + pack_start(*estop); + pack_start(*scaltm); + pack_start(*rewei); + // pack_start(*softradiustm); // Always bad with TM ?? + pack_start(*sensitm); +} + +void LocallabTone::disableListener() +{ + LocallabTool::disableListener(); + + equiltmConn.block(true); +} + +void LocallabTone::enableListener() +{ + LocallabTool::enableListener(); + + equiltmConn.block(false); +} + +void LocallabTone::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).exptonemap); + amount->setValue(pp->locallab.spots.at(index).amount); + stren->setValue(pp->locallab.spots.at(index).stren); + equiltm->set_active(pp->locallab.spots.at(index).equiltm); + gamma->setValue(pp->locallab.spots.at(index).gamma); + satur->setValue(pp->locallab.spots.at(index).satur); + estop->setValue(pp->locallab.spots.at(index).estop); + scaltm->setValue(pp->locallab.spots.at(index).scaltm); + rewei->setValue(pp->locallab.spots.at(index).rewei); + softradiustm->setValue(pp->locallab.spots.at(index).softradiustm); + sensitm->setValue(pp->locallab.spots.at(index).sensitm); + enaMask->set_active(pp->locallab.spots.at(index).enatmMask); + CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmasktmcurve); + LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmasktmcurve); + HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmasktmcurve); + blendMask->setValue(pp->locallab.spots.at(index).blendmasktm); + radMask->setValue(pp->locallab.spots.at(index).radmasktm); + chroMask->setValue(pp->locallab.spots.at(index).chromasktm); + gamMask->setValue(pp->locallab.spots.at(index).gammasktm); + sloMask->setValue(pp->locallab.spots.at(index).slomasktm); + } + + // Enable all listeners + enableListener(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabTone::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).exptonemap = exp->getEnabled(); + pp->locallab.spots.at(index).amount = amount->getValue(); + pp->locallab.spots.at(index).stren = stren->getValue(); + pp->locallab.spots.at(index).equiltm = equiltm->get_active(); + pp->locallab.spots.at(index).gamma = gamma->getValue(); + pp->locallab.spots.at(index).satur = satur->getValue(); + pp->locallab.spots.at(index).estop = estop->getValue(); + pp->locallab.spots.at(index).scaltm = scaltm->getValue(); + pp->locallab.spots.at(index).rewei = rewei->getIntValue(); + pp->locallab.spots.at(index).softradiustm = softradiustm->getValue(); + pp->locallab.spots.at(index).sensitm = sensitm->getIntValue(); + pp->locallab.spots.at(index).enatmMask = enaMask->get_active(); + pp->locallab.spots.at(index).LLmasktmcurve = LLMaskShape->getCurve(); + pp->locallab.spots.at(index).CCmasktmcurve = CCMaskShape->getCurve(); + pp->locallab.spots.at(index).HHmasktmcurve = HHMaskShape->getCurve(); + pp->locallab.spots.at(index).blendmasktm = blendMask->getIntValue(); + pp->locallab.spots.at(index).radmasktm = radMask->getValue(); + pp->locallab.spots.at(index).chromasktm = chroMask->getValue(); + pp->locallab.spots.at(index).gammasktm = gamMask->getValue(); + pp->locallab.spots.at(index).slomasktm = sloMask->getValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabTone::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabTone::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == amount) { + if (listener) { + listener->panelChanged(Evlocallabamount, + amount->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == stren) { + if (listener) { + listener->panelChanged(Evlocallabstren, + stren->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gamma) { + if (listener) { + listener->panelChanged(Evlocallabgamma, + gamma->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == satur) { + if (listener) { + listener->panelChanged(Evlocallabsatur, + satur->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == estop) { + if (listener) { + listener->panelChanged(Evlocallabestop, + estop->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == scaltm) { + if (listener) { + listener->panelChanged(Evlocallabscaltm, + scaltm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == rewei) { + if (listener) { + listener->panelChanged(Evlocallabrewei, + rewei->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == softradiustm) { + if (listener) { + listener->panelChanged(Evlocallabsoftradiustm, + softradiustm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensitm) { + if (listener) { + listener->panelChanged(Evlocallabsensitm, + sensitm->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendMask) { + if (listener) { + listener->panelChanged(Evlocallabblendmasktm, + blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radMask) { + if (listener) { + listener->panelChanged(Evlocallabradmasktm, + radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chroMask) { + if (listener) { + listener->panelChanged(Evlocallabchromasktm, + chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gamMask) { + if (listener) { + listener->panelChanged(Evlocallabgammasktm, + gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sloMask) { + if (listener) { + listener->panelChanged(Evlocallabslomasktm, + sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabTone::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == CCMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabCCmasktmshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabLLmasktmshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabHHmasktmshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabTone::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenatonemap, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenatonemap, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabTone::enaMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaMask->get_active()) { + listener->panelChanged(EvLocallabEnatmMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnatmMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabTone::showMaskMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvLocallabEnatmMask, ""); // TODO Use generic event for mask preview + } +} + +void LocallabTone::equiltmChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (equiltm->get_active()) { + listener->panelChanged(Evlocallabequiltm, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabequiltm, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +/* ==== LocallabRetinex ==== */ +LocallabRetinex::LocallabRetinex(): + LocallabTool(this, "Locallab Retinex", M("TP_LOCALLAB_RETI"), true, MaskWithTrMap), + + // Retinex specific widgets + retinexMethod(Gtk::manage(new MyComboBoxText())), + fftwreti(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTW")))), + equilret(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_EQUIL")))), + str(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STR"), 0., 100., 0.1, 0.0))), + chrrt(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHRRT"), 0.0, 100.0, 0.1, 0.0))), + neigh(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NEIGH"), MINNEIGH, MAXNEIGH, 0.5, CENTERNEIGH, nullptr, nullptr, &retiSlider2neigh, &retiNeigh2Slider))), + vart(Gtk::manage(new Adjuster(M("TP_LOCALLAB_VART"), 4.0, 500., 0.1, 70.))), + scalereti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SCALERETI"), 1.0, 10.0, 1., 3.))), + limd(Gtk::manage(new Adjuster(M("TP_LOCALLAB_THRESRETI"), 1.2, 100.0, 0.1, 8.))), + darkness(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DARKRETI"), 0.01, 3.0, 0.01, 1.))), + lightnessreti(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LIGHTRETI"), 0.01, 3.0, 0.01, 1.))), + dehaz(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DEHAZ"), 0, 100, 1, 0))), + softradiusret(Gtk::manage(new Adjuster(M("TP_LOCALLAB_GUIDFILTER"), 0.0, 100.0, 0.1, 0.))), + sensih(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIH"), 0, 100, 1, 30))), + LocalcurveEditorgainT(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_TRANSMISSIONGAIN"))), + inversret(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) +{ + const bool showtooltip = options.showtooltip; + + retinexMethod->append(M("TP_RETINEX_LOW")); + retinexMethod->append(M("TP_RETINEX_UNIFORM")); + retinexMethod->append(M("TP_RETINEX_HIGH")); + retinexMethod->set_active(0); + + if (showtooltip) { + retinexMethod->set_tooltip_markup(M("TP_LOCRETI_METHOD_TOOLTIP")); + } + + retinexMethodConn = retinexMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabRetinex::retinexMethodChanged)); + + if (showtooltip) { + fftwreti->set_tooltip_text(M("TP_LOCALLAB_RETI_FFTW_TOOLTIP")); + } + + fftwretiConn = fftwreti->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::fftwretiChanged)); + + equilretConn = equilret->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::equilretChanged)); + + str->setAdjusterListener(this); + + chrrt->setAdjusterListener(this); + + if (showtooltip) { + neigh->set_tooltip_text(M("TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP")); + } + + neigh->setAdjusterListener(this); + + if (showtooltip) { + vart->set_tooltip_text(M("TP_LOCALLAB_RETI_NEIGH_VART_TOOLTIP")); + } + + vart->setAdjusterListener(this); + + scalereti->setAdjusterListener(this); + + limd->setAdjusterListener(this); + + darkness->setAdjusterListener(this); + + lightnessreti->setAdjusterListener(this); + + dehaz->setAdjusterListener(this); + + if (showtooltip) { + softradiusret->set_tooltip_text(M("TP_LOCALLAB_GUIDFILTER_TOOLTIP")); + } + + softradiusret->setAdjusterListener(this); + + if (showtooltip) { + sensih->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); + } + + sensih->setAdjusterListener(this); + + LocalcurveEditorgainT->setCurveListener(this); + + cTgainshape = static_cast(LocalcurveEditorgainT->addCurve(CT_Flat, "", nullptr, false, false)); + cTgainshape->setIdentityValue(0.); + cTgainshape->setResetCurve(FlatCurveType(LocallabParams::DEF_RET_CURVE.at(0)), LocallabParams::DEF_RET_CURVE); + + if (showtooltip) { + cTgainshape->setTooltip(M("TP_RETINEX_GAINTRANSMISSION_TOOLTIP")); + } + + LocalcurveEditorgainT->curveListComplete(); + + inversretConn = inversret->signal_toggled().connect(sigc::mem_fun(*this, &LocallabRetinex::inversretChanged)); + + pack_start(*retinexMethod); + pack_start(*fftwreti); + pack_start(*equilret); + pack_start(*str); + pack_start(*chrrt); + pack_start(*neigh); + pack_start(*vart); + pack_start(*scalereti); + pack_start(*limd); + pack_start(*darkness); + pack_start(*lightnessreti); + pack_start(*dehaz); + pack_start(*softradiusret); + pack_start(*sensih); + pack_start(*LocalcurveEditorgainT, Gtk::PACK_SHRINK, 4); // Padding is mandatory to correct behavior of curve editor + pack_start(*inversret); +} + +LocallabRetinex::~LocallabRetinex() +{ + delete LocalcurveEditorgainT; +} + +void LocallabRetinex::disableListener() +{ + LocallabTool::disableListener(); + + retinexMethodConn.block(true); + fftwretiConn.block(true); + equilretConn.block(true); + inversretConn.block(true); +} + +void LocallabRetinex::enableListener() +{ + LocallabTool::enableListener(); + + retinexMethodConn.block(false); + fftwretiConn.block(false); + equilretConn.block(false); + inversretConn.block(false); +} + +void LocallabRetinex::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expreti); + + if (pp->locallab.spots.at(index).retinexMethod == "low") { + retinexMethod->set_active(0); + } else if (pp->locallab.spots.at(index).retinexMethod == "uni") { + retinexMethod->set_active(1); + } else { + retinexMethod->set_active(2); + } + + fftwreti->set_active(pp->locallab.spots.at(index).fftwreti); + equilret->set_active(pp->locallab.spots.at(index).equilret); + str->setValue(pp->locallab.spots.at(index).str); + chrrt->setValue(pp->locallab.spots.at(index).chrrt); + neigh->setValue(pp->locallab.spots.at(index).neigh); + vart->setValue(pp->locallab.spots.at(index).vart); + scalereti->setValue(pp->locallab.spots.at(index).scalereti); + limd->setValue(pp->locallab.spots.at(index).limd); + darkness->setValue(pp->locallab.spots.at(index).darkness); + lightnessreti->setValue(pp->locallab.spots.at(index).lightnessreti); + dehaz->setValue(pp->locallab.spots.at(index).dehaz); + softradiusret->setValue(pp->locallab.spots.at(index).softradiusret); + sensih->setValue(pp->locallab.spots.at(index).sensih); + cTgainshape->setCurve(pp->locallab.spots.at(index).localTgaincurve); + inversret->set_active(pp->locallab.spots.at(index).inversret); + enaMask->set_active(pp->locallab.spots.at(index).enaretiMask); + enaMaskTrMap->set_active(pp->locallab.spots.at(index).enaretiMasktmap); + CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskreticurve); + LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskreticurve); + HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskreticurve); + blendMask->setValue(pp->locallab.spots.at(index).blendmaskreti); + radMask->setValue(pp->locallab.spots.at(index).radmaskreti); + chroMask->setValue(pp->locallab.spots.at(index).chromaskreti); + gamMask->setValue(pp->locallab.spots.at(index).gammaskreti); + sloMask->setValue(pp->locallab.spots.at(index).slomaskreti); + } + + // Enable all listeners + enableListener(); + + // Update Retinex GUI according to scalereti adjuster value + updateRetinexGUI(); + + // Update Retinex GUI according to inversret button state + updateRetinexGUI2(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabRetinex::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expsoft = exp->getEnabled(); + + pp->locallab.spots.at(index).expreti = exp->getEnabled(); + + if (retinexMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).retinexMethod = "low"; + } else if (retinexMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).retinexMethod = "uni"; + } else if (retinexMethod->get_active_row_number() == 2) { + pp->locallab.spots.at(index).retinexMethod = "high"; + } + + pp->locallab.spots.at(index).fftwreti = fftwreti->get_active(); + pp->locallab.spots.at(index).equilret = equilret->get_active(); + pp->locallab.spots.at(index).str = str->getValue(); + pp->locallab.spots.at(index).chrrt = chrrt->getValue(); + pp->locallab.spots.at(index).neigh = neigh->getValue(); + pp->locallab.spots.at(index).vart = vart->getValue(); + pp->locallab.spots.at(index).scalereti = scalereti->getValue(); + pp->locallab.spots.at(index).limd = limd->getValue(); + pp->locallab.spots.at(index).darkness = darkness->getValue(); + pp->locallab.spots.at(index).lightnessreti = lightnessreti->getValue(); + pp->locallab.spots.at(index).dehaz = dehaz->getIntValue(); + pp->locallab.spots.at(index).softradiusret = softradiusret->getValue(); + pp->locallab.spots.at(index).sensih = sensih->getIntValue(); + pp->locallab.spots.at(index).localTgaincurve = cTgainshape->getCurve(); + pp->locallab.spots.at(index).inversret = inversret->get_active(); + pp->locallab.spots.at(index).enaretiMask = enaMask->get_active(); + pp->locallab.spots.at(index).enaretiMasktmap = enaMaskTrMap->get_active(); + pp->locallab.spots.at(index).LLmaskreticurve = LLMaskShape->getCurve(); + pp->locallab.spots.at(index).CCmaskreticurve = CCMaskShape->getCurve(); + pp->locallab.spots.at(index).HHmaskreticurve = HHMaskShape->getCurve(); + pp->locallab.spots.at(index).blendmaskreti = blendMask->getIntValue(); + pp->locallab.spots.at(index).radmaskreti = radMask->getValue(); + pp->locallab.spots.at(index).chromaskreti = chroMask->getValue(); + pp->locallab.spots.at(index).gammaskreti = gamMask->getValue(); + pp->locallab.spots.at(index).slomaskreti = sloMask->getValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabRetinex::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabRetinex::adjusterChanged(Adjuster* a, double newval) +{ + // Update Retinex GUI according to scalereti adjuster value + if (a == scalereti) { + updateRetinexGUI(); + } + + if (isLocActivated && exp->getEnabled()) { + if (a == str) { + if (listener) { + listener->panelChanged(Evlocallabstr, + str->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chrrt) { + if (listener) { + listener->panelChanged(Evlocallabchrrt, + chrrt->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == neigh) { + if (listener) { + listener->panelChanged(Evlocallabneigh, + neigh->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == vart) { + if (listener) { + listener->panelChanged(Evlocallabvart, + vart->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == scalereti) { + if (listener) { + listener->panelChanged(Evlocallabscalereti, + scalereti->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == limd) { + if (listener) { + listener->panelChanged(Evlocallablimd, + limd->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == darkness) { + if (listener) { + listener->panelChanged(Evlocallabdarkness, + darkness->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == lightnessreti) { + if (listener) { + listener->panelChanged(Evlocallablightnessreti, + lightnessreti->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == dehaz) { + if (listener) { + listener->panelChanged(Evlocallabdehaz, + dehaz->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == softradiusret) { + if (listener) { + listener->panelChanged(Evlocallabsoftradiusret, + softradiusret->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensih) { + if (listener) { + listener->panelChanged(Evlocallabsensih, + sensih->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendMask) { + if (listener) { + listener->panelChanged(Evlocallabblendmaskreti, + blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radMask) { + if (listener) { + listener->panelChanged(Evlocallabradmaskreti, + radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chroMask) { + if (listener) { + listener->panelChanged(Evlocallabchromaskreti, + chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gamMask) { + if (listener) { + listener->panelChanged(Evlocallabgammaskreti, + gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sloMask) { + if (listener) { + listener->panelChanged(Evlocallabslomaskreti, + sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == cTgainshape) { + if (listener) { + listener->panelChanged(EvlocallabCTgainCurve, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == CCMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabCCmaskretishape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskretishape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabHHmaskretishape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenareti, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenareti, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::enaMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaMask->get_active()) { + listener->panelChanged(EvLocallabEnaretiMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaretiMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::enaMaskTrMapChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaMaskTrMap->get_active()) { + listener->panelChanged(EvLocallabEnaretiMasktmap, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnaretiMasktmap, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::showMaskMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskretiMethod, ""); // TODO Use generic event for mask preview + } +} + +void LocallabRetinex::retinexMethodChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallabretinexMethod, + retinexMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabRetinex::fftwretiChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (fftwreti->get_active()) { + listener->panelChanged(Evlocallabfftwreti, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabfftwreti, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::equilretChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (inversret->get_active()) { + listener->panelChanged(Evlocallabequilret, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabequilret, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::inversretChanged() +{ + // Update Retinex GUI according to inversret button state + updateRetinexGUI2(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (inversret->get_active()) { + listener->panelChanged(Evlocallabinversret, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabinversret, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabRetinex::updateRetinexGUI() +{ + // Update Retinex GUI according to scalereti adjuster value + if (scalereti->getValue() == 1) { + // limd->hide(); + LocalcurveEditorgainT->hide(); + retinexMethod->hide(); + } else { + // limd->show(); + LocalcurveEditorgainT->show(); + retinexMethod->show(); + } +} + +void LocallabRetinex::updateRetinexGUI2() +{ + // Update Retinex GUI according to inversret button state + if (inversret->get_active()) { + maskExp->hide(); + } else { + maskExp->show(); + } +} + +/* ==== LocallabSharp ==== */ +LocallabSharp::LocallabSharp(): + LocallabTool(this, "Locallab Sharpening", M("TP_LOCALLAB_SHARP"), true, MaskNone), + + // Sharpening specific widgets + sharcontrast(Gtk::manage(new Adjuster(M("TP_SHARPENING_CONTRAST"), 0, 200, 1, 20))), + sharradius(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARRADIUS"), 0.4, 2.5, 0.01, 0.75))), + sharamount(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARAMOUNT"), 0, 100, 1, 100))), + shardamping(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARDAMPING"), 0, 100, 1, 0))), + shariter(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARITER"), 5, 100, 1, 30))), + sharblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARBLUR"), 0.2, 2.0, 0.05, 0.2))), + sensisha(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIS"), 0, 100, 1, 19))), + inverssha(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_INVERS")))) +{ + const bool showtooltip = options.showtooltip; + + sharcontrast->setAdjusterListener(this); + + sharradius->setAdjusterListener(this); + + sharamount->setAdjusterListener(this); + + shardamping->setAdjusterListener(this); + + shariter->setAdjusterListener(this); + + sharblur->setAdjusterListener(this); + + if (showtooltip) { + sensisha->set_tooltip_text(M("TP_LOCALLAB_SENSIS_TOOLTIP")); + } + + sensisha->setAdjusterListener(this); + + inversshaConn = inverssha->signal_toggled().connect(sigc::mem_fun(*this, &LocallabSharp::inversshaChanged)); + + pack_start(*sharcontrast); + pack_start(*sharradius); + pack_start(*sharamount); + pack_start(*shardamping); + pack_start(*shariter); + pack_start(*sharblur); + pack_start(*sensisha); + pack_start(*inverssha); +} + +void LocallabSharp::disableListener() +{ + LocallabTool::disableListener(); + + inversshaConn.block(true); +} + +void LocallabSharp::enableListener() +{ + LocallabTool::enableListener(); + + inversshaConn.block(false); +} + +void LocallabSharp::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expsharp); + sharcontrast->setValue(pp->locallab.spots.at(index).sharcontrast); + sharradius->setValue(pp->locallab.spots.at(index).sharradius); + sharamount->setValue(pp->locallab.spots.at(index).sharamount); + shardamping->setValue(pp->locallab.spots.at(index).shardamping); + shariter->setValue(pp->locallab.spots.at(index).shariter); + sharblur->setValue(pp->locallab.spots.at(index).sharblur); + sensisha->setValue(pp->locallab.spots.at(index).sensisha); + inverssha->set_active(pp->locallab.spots.at(index).inverssha); + } + + // Enable all listeners + enableListener(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabSharp::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expsharp = exp->getEnabled(); + pp->locallab.spots.at(index).sharcontrast = sharcontrast->getIntValue(); + pp->locallab.spots.at(index).sharradius = sharradius->getValue(); + pp->locallab.spots.at(index).sharamount = sharamount->getIntValue(); + pp->locallab.spots.at(index).shardamping = shardamping->getIntValue(); + pp->locallab.spots.at(index).shariter = shariter->getIntValue(); + pp->locallab.spots.at(index).sharblur = sharblur->getValue(); + pp->locallab.spots.at(index).sensisha = sensisha->getIntValue(); + pp->locallab.spots.at(index).inverssha = inverssha->get_active(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabSharp::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabSharp::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == sharcontrast) { + if (listener) { + listener->panelChanged(Evlocallabsharcontrast, + sharcontrast->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sharradius) { + if (listener) { + listener->panelChanged(Evlocallabsharradius, + sharradius->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sharamount) { + if (listener) { + listener->panelChanged(Evlocallabsharamount, + sharamount->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shardamping) { + if (listener) { + listener->panelChanged(Evlocallabshardamping, + shardamping->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == shariter) { + if (listener) { + listener->panelChanged(Evlocallabshariter, + shariter->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sharblur) { + if (listener) { + listener->panelChanged(Evlocallabsharblur, + sharblur->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensisha) { + if (listener) { + listener->panelChanged(Evlocallabsensis, + sensisha->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabSharp::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenasharp, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenasharp, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabSharp::inversshaChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (inverssha->get_active()) { + listener->panelChanged(Evlocallabinverssha, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabinverssha, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +/* ==== LocallabContrast ==== */ +LocallabContrast::LocallabContrast(): + LocallabTool(this, "Locallab Local Constrast", M("TP_LOCALLAB_LOC_CONTRAST"), false, MaskNone), + + // Local constrast specific widgets + localcontMethod(Gtk::manage(new MyComboBoxText())), + lcradius(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_RADIUS"), 20, 400, 1, 80))), + lcamount(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_AMOUNT"), 0, 1.0, 0.01, 0))), + lcdarkness(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_DARKNESS"), 0, 3.0, 0.01, 1.0))), + lclightness(Gtk::manage(new Adjuster(M("TP_LOCALCONTRAST_LIGHTNESS"), 0, 3.0, 0.01, 1.0))), + LocalcurveEditorwav(new CurveEditorGroup(options.lastlocalCurvesDir, M("TP_LOCALLAB_WAV"))), + levelwav(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LEVELWAV"), 3, 9, 1, 4))), + residcont(Gtk::manage(new Adjuster(M("TP_LOCALLAB_RESIDCONT"), -100, 100, 1, 0))), + sensilc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIS"), 0, 100, 1, 19))), + fftwlc(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_FFTW")))) +{ + const bool showtooltip = options.showtooltip; + + localcontMethod->append(M("TP_LOCALLAB_LOCCONT")); + localcontMethod->append(M("TP_LOCALLAB_WAVE")); + localcontMethod->set_active(0); + + if (showtooltip) { + // localcontMethod->set_tooltip_markup(M("TP_LOCALLAB_LOCMETHOD_TOOLTIP")); + } + + localcontMethodConn = localcontMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabContrast::localcontMethodChanged)); + + lcradius->setAdjusterListener(this); + + lcamount->setAdjusterListener(this); + + lcdarkness->setAdjusterListener(this); + + lclightness->setAdjusterListener(this); + + LocalcurveEditorwav->setCurveListener(this); + + wavshape = static_cast(LocalcurveEditorwav->addCurve(CT_Flat, "", nullptr, false, false)); + wavshape->setIdentityValue(0.); + wavshape->setResetCurve(FlatCurveType(LocallabParams::DEF_LC_CURVE.at(0)), LocallabParams::DEF_LC_CURVE); + + if (showtooltip) { + wavshape->setTooltip(M("TP_RETINEX_WAV_TOOLTIP")); + } + + LocalcurveEditorwav->curveListComplete(); + + if (showtooltip) { + levelwav->set_tooltip_markup(M("TP_LOCALLAB_LEVELWAV_TOOLTIP")); + } + + levelwav->setAdjusterListener(this); + + residcont->setAdjusterListener(this); + + sensilc->setAdjusterListener(this); + + if (showtooltip) { + fftwlc->set_tooltip_text(M("TP_LOCALLAB_LC_FFTW_TOOLTIP")); + } + + fftwlcConn = fftwlc->signal_toggled().connect(sigc::mem_fun(*this, &LocallabContrast::fftwlcChanged)); + + pack_start(*localcontMethod); + pack_start(*lcradius); + pack_start(*lcamount); + pack_start(*lcdarkness); + pack_start(*lclightness); + pack_start(*LocalcurveEditorwav, Gtk::PACK_SHRINK, 4); + pack_start(*levelwav); + pack_start(*residcont); + pack_start(*sensilc); + pack_start(*fftwlc); +} + +LocallabContrast::~LocallabContrast() +{ + delete LocalcurveEditorwav; +} + +void LocallabContrast::disableListener() +{ + LocallabTool::disableListener(); + + localcontMethodConn.block(true); + fftwlcConn.block(true); +} + +void LocallabContrast::enableListener() +{ + LocallabTool::enableListener(); + + localcontMethodConn.block(false); + fftwlcConn.block(false); +} + +void LocallabContrast::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expcontrast); + + if (pp->locallab.spots.at(index).localcontMethod == "loc") { + localcontMethod->set_active(0); + } else if (pp->locallab.spots.at(index).localcontMethod == "wav") { + localcontMethod->set_active(1); + } + + lcradius->setValue(pp->locallab.spots.at(index).lcradius); + lcamount->setValue(pp->locallab.spots.at(index).lcamount); + lcdarkness->setValue(pp->locallab.spots.at(index).lcdarkness); + lclightness->setValue(pp->locallab.spots.at(index).lclightness); + wavshape->setCurve(pp->locallab.spots.at(index).locwavcurve); + levelwav->setValue(pp->locallab.spots.at(index).levelwav); + residcont->setValue(pp->locallab.spots.at(index).residcont); + sensilc->setValue(pp->locallab.spots.at(index).sensilc); + fftwlc->set_active(pp->locallab.spots.at(index).fftwlc); + } + + // Enable all listeners + enableListener(); + + // Update Local constrast GUI according to localcontMethod combobox value + updateContrastGUI(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabContrast::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expcontrast = exp->getEnabled(); + + if (localcontMethod->get_active_row_number() == 0) { + pp->locallab.spots.at(index).localcontMethod = "loc"; + } else if (localcontMethod->get_active_row_number() == 1) { + pp->locallab.spots.at(index).localcontMethod = "wav"; + } + + pp->locallab.spots.at(index).lcradius = lcradius->getIntValue(); + pp->locallab.spots.at(index).lcamount = lcamount->getValue(); + pp->locallab.spots.at(index).lcdarkness = lcdarkness->getValue(); + pp->locallab.spots.at(index).lclightness = lclightness->getValue(); + pp->locallab.spots.at(index).locwavcurve = wavshape->getCurve(); + pp->locallab.spots.at(index).levelwav = levelwav->getIntValue(); + pp->locallab.spots.at(index).residcont = residcont->getValue(); + pp->locallab.spots.at(index).sensilc = sensilc->getIntValue(); + pp->locallab.spots.at(index).fftwlc = fftwlc->get_active(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabContrast::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabContrast::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == lcradius) { + if (listener) { + listener->panelChanged(Evlocallablcradius, + lcradius->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == lcamount) { + if (listener) { + listener->panelChanged(Evlocallablcamount, + lcamount->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == lcdarkness) { + if (listener) { + listener->panelChanged(Evlocallablcdarkness, + lcdarkness->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == lclightness) { + if (listener) { + listener->panelChanged(Evlocallablclightness, + lclightness->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == levelwav) { + if (listener) { + listener->panelChanged(Evlocallablevelwav, + levelwav->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == residcont) { + if (listener) { + listener->panelChanged(Evlocallabresidcont, + residcont->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensilc) { + if (listener) { + listener->panelChanged(Evlocallabsensilc, + sensilc->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == wavshape) { + if (listener) { + listener->panelChanged(EvlocallabwavCurve, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenacontrast, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenacontrast, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::localcontMethodChanged() +{ + // Update Local constrast GUI according to localcontMethod combobox value + updateContrastGUI(); + + if (isLocActivated && exp->getEnabled()) { + if (listener) { + listener->panelChanged(EvlocallablocalcontMethod, + localcontMethod->get_active_text() + " (" + escapeHtmlChars(spotName) + ")"); + } + } +} + +void LocallabContrast::fftwlcChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (fftwlc->get_active()) { + listener->panelChanged(Evlocallabfftwlc, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(Evlocallabfftwlc, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabContrast::updateContrastGUI() +{ + // Update Local constrast GUI according to localcontMethod combobox value + if (localcontMethod->get_active_row_number() == 0) { + lcradius->show(); + lcamount->show(); + lcdarkness->show(); + lclightness->show(); + LocalcurveEditorwav->hide(); + levelwav->hide(); + residcont->hide(); + fftwlc->show(); + } else if (localcontMethod->get_active_row_number() == 1) { + lcradius->hide(); + lcamount->hide(); + lcdarkness->hide(); + lclightness->hide(); + LocalcurveEditorwav->show(); + levelwav->show(); + residcont->show(); + fftwlc->hide(); + } +} + +/* ==== LocallabCBDL ==== */ +LocallabCBDL::LocallabCBDL(): + LocallabTool(this, "Locallab CBDL", M("TP_LOCALLAB_CBDL"), true, MaskNormal), + + // CBDL specific widgets + chromacbdl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CHROMACBDL"), 0., 1.5, 0.01, 0.))), + threshold(Gtk::manage(new Adjuster(M("TP_DIRPYREQUALIZER_THRESHOLD"), 0, 1., 0.01, 0.2))), + blurcbdl(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BLURCBDL"), 0., 100., 0.1, 0.))), + clarityml(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CLARITYML"), 0.1, 100., 0.1, 0.1))), + contresid(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTRESID"), -100, 100, 1, 0))), + softradiuscb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.1, 0.))), + sensicb(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSICB"), 0, 100, 1, 15))), + + lumacontrastMinusButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS")))), + lumaneutralButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMANEUTRAL")))), + lumacontrastPlusButton(Gtk::manage(new Gtk::Button(M("TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS")))) +{ + const bool showtooltip = options.showtooltip; + + if (showtooltip) { + exp->set_tooltip_text(M("TP_LOCALLAB_EXPCBDL_TOOLTIP")); + } + + for (int i = 0; i < 6; i++) { + Glib::ustring ss; + ss = Glib::ustring::format(i); + + if (i == 0) { + ss += Glib::ustring::compose(" (%1)", M("TP_DIRPYREQUALIZER_LUMAFINEST")); + } else if (i == 5) { + ss += Glib::ustring::compose(" (%1)", M("TP_DIRPYREQUALIZER_LUMACOARSEST")); + } + + multiplier[i] = Gtk::manage(new Adjuster(std::move(ss), 0.0, 4.0, 0.01, 1.0)); + multiplier[i]->setAdjusterListener(this); + } + + if (showtooltip) { + chromacbdl->set_tooltip_text(M("TP_LOCALLAB_CHROMACB_TOOLTIP")); + } + + chromacbdl->setAdjusterListener(this); + + threshold->setAdjusterListener(this); + + blurcbdl->setAdjusterListener(this); + + clarityml->setAdjusterListener(this); + + contresid->setAdjusterListener(this); + + softradiuscb->setAdjusterListener(this); + + if (showtooltip) { + sensicb->set_tooltip_text(M("TP_LOCALLAB_SENSIH_TOOLTIP")); + } + + sensicb->setAdjusterListener(this); + + lumacontrastMinusPressedConn = lumacontrastMinusButton->signal_pressed().connect(sigc::mem_fun(*this, &LocallabCBDL::lumacontrastMinusPressed)); + + lumaneutralPressedConn = lumaneutralButton->signal_pressed().connect(sigc::mem_fun(*this, &LocallabCBDL::lumaneutralPressed)); + + lumacontrastPlusPressedConn = lumacontrastPlusButton->signal_pressed().connect(sigc::mem_fun(*this, &LocallabCBDL::lumacontrastPlusPressed)); + + Gtk::HBox* buttonBox = Gtk::manage(new Gtk::HBox(true, 10)); + buttonBox->pack_start(*lumacontrastMinusButton); + buttonBox->pack_start(*lumaneutralButton); + buttonBox->pack_start(*lumacontrastPlusButton); + pack_start(*buttonBox); + + for (int i = 0; i < 6; i++) { + pack_start(*multiplier[i]); + } + + Gtk::HSeparator* const separator = Gtk::manage(new Gtk::HSeparator()); + pack_start(*separator, Gtk::PACK_SHRINK, 2); + pack_start(*chromacbdl); + pack_start(*threshold); + pack_start(*blurcbdl); + Gtk::Frame* const residFrame = Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_RESID"))); + residFrame->set_label_align(0.025, 0.5); + ToolParamBlock* const residBox = Gtk::manage(new ToolParamBlock()); + residBox->pack_start(*clarityml); + residBox->pack_start(*contresid); + residFrame->add(*residBox); + pack_start(*residFrame); + pack_start(*softradiuscb); + pack_start(*sensicb); +} + +void LocallabCBDL::disableListener() +{ + LocallabTool::disableListener(); + + lumacontrastMinusPressedConn.block(true); + lumaneutralPressedConn.block(true); + lumacontrastPlusPressedConn.block(true); +} + +void LocallabCBDL::enableListener() +{ + LocallabTool::enableListener(); + + lumacontrastMinusPressedConn.block(false); + lumaneutralPressedConn.block(false); + lumacontrastPlusPressedConn.block(false); +} + +void LocallabCBDL::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expcbdl); + + for (int i = 0; i < 6; i++) { + multiplier[i]->setValue(pp->locallab.spots.at(index).mult[i]); + } + + chromacbdl->setValue(pp->locallab.spots.at(index).chromacbdl); + threshold->setValue(pp->locallab.spots.at(index).threshold); + blurcbdl->setValue(pp->locallab.spots.at(index).blurcbdl); + clarityml->setValue(pp->locallab.spots.at(index).clarityml); + contresid->setValue(pp->locallab.spots.at(index).contresid); + softradiuscb->setValue(pp->locallab.spots.at(index).softradiuscb); + sensicb->setValue(pp->locallab.spots.at(index).sensicb); + enaMask->set_active(pp->locallab.spots.at(index).enacbMask); + CCMaskShape->setCurve(pp->locallab.spots.at(index).CCmaskcbcurve); + LLMaskShape->setCurve(pp->locallab.spots.at(index).LLmaskcbcurve); + HHMaskShape->setCurve(pp->locallab.spots.at(index).HHmaskcbcurve); + blendMask->setValue(pp->locallab.spots.at(index).blendmaskcb); + radMask->setValue(pp->locallab.spots.at(index).radmaskcb); + chroMask->setValue(pp->locallab.spots.at(index).chromaskcb); + gamMask->setValue(pp->locallab.spots.at(index).gammaskcb); + sloMask->setValue(pp->locallab.spots.at(index).slomaskcb); + } + + // Enable all listeners + enableListener(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabCBDL::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expcbdl = exp->getEnabled(); + + for (int i = 0; i < 6; i++) { + pp->locallab.spots.at(index).mult[i] = multiplier[i]->getValue(); + } + + pp->locallab.spots.at(index).chromacbdl = chromacbdl->getValue(); + pp->locallab.spots.at(index).threshold = threshold->getValue(); + pp->locallab.spots.at(index).blurcbdl = blurcbdl->getValue(); + pp->locallab.spots.at(index).clarityml = clarityml->getValue(); + pp->locallab.spots.at(index).contresid = contresid->getIntValue(); + pp->locallab.spots.at(index).softradiuscb = softradiuscb->getValue(); + pp->locallab.spots.at(index).sensicb = sensicb->getIntValue(); + pp->locallab.spots.at(index).enacbMask = enaMask->get_active(); + pp->locallab.spots.at(index).LLmaskcbcurve = LLMaskShape->getCurve(); + pp->locallab.spots.at(index).CCmaskcbcurve = CCMaskShape->getCurve(); + pp->locallab.spots.at(index).HHmaskcbcurve = HHMaskShape->getCurve(); + pp->locallab.spots.at(index).blendmaskcb = blendMask->getIntValue(); + pp->locallab.spots.at(index).radmaskcb = radMask->getValue(); + pp->locallab.spots.at(index).chromaskcb = chroMask->getValue(); + pp->locallab.spots.at(index).gammaskcb = gamMask->getValue(); + pp->locallab.spots.at(index).slomaskcb = sloMask->getValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabCBDL::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabCBDL::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == multiplier[0] || a == multiplier[1] || a == multiplier[2] || a == multiplier[3] || a == multiplier[4] || a == multiplier[5]) { + if (listener) { + listener->panelChanged(EvlocallabEqualizer, + Glib::ustring::compose("%1, %2, %3, %4, %5, %6", + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[0]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[1]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[2]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[3]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[4]->getValue()), + Glib::ustring::format(std::fixed, std::setprecision(2), multiplier[5]->getValue())) + + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chromacbdl) { + if (listener) { + listener->panelChanged(Evlocallabchromacbdl, + chromacbdl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == threshold) { + if (listener) { + listener->panelChanged(EvlocallabThresho, + threshold->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blurcbdl) { + if (listener) { + listener->panelChanged(EvLocallabblurcbdl, + blurcbdl->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == clarityml) { + if (listener) { + listener->panelChanged(EvLocallabclarityml, + clarityml->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == contresid) { + if (listener) { + listener->panelChanged(EvLocallabcontresid, + contresid->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == softradiuscb) { + if (listener) { + listener->panelChanged(Evlocallabsoftradiuscb, + softradiuscb->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensicb) { + if (listener) { + listener->panelChanged(Evlocallabsensicb, + sensicb->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == blendMask) { + if (listener) { + listener->panelChanged(Evlocallabblendmaskcb, + blendMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == radMask) { + if (listener) { + listener->panelChanged(Evlocallabradmaskcb, + radMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == chroMask) { + if (listener) { + listener->panelChanged(Evlocallabchromaskcb, + chroMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == gamMask) { + if (listener) { + listener->panelChanged(Evlocallabgammaskcb, + gamMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sloMask) { + if (listener) { + listener->panelChanged(Evlocallabslomaskcb, + sloMask->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabCBDL::curveChanged(CurveEditor* ce) +{ + if (isLocActivated && exp->getEnabled()) { + if (ce == CCMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabCCmaskcbshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == LLMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabLLmaskcbshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (ce == HHMaskShape) { + if (listener) { + listener->panelChanged(EvlocallabHHmaskcbshape, + M("HISTORY_CUSTOMCURVE") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabCBDL::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenacbdl, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenacbdl, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabCBDL::enaMaskChanged() +{ + if (isLocActivated && exp->getEnabled()) { + if (listener) { + if (enaMask->get_active()) { + listener->panelChanged(EvLocallabEnacbMask, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocallabEnacbMask, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabCBDL::showMaskMethodChanged() +{ + // If mask preview is activated, deactivate all other tool mask preview + if (locToolListener) { + locToolListener->resetOtherMaskView(this); + } + + if (listener) { + listener->panelChanged(EvlocallabshowmaskcbMethod, ""); // TODO Use generic event for mask preview + } +} + +void LocallabCBDL::lumacontrastMinusPressed() +{ + for (int i = 0; i < 6; i++) { + float inc = - (5 - i); + multiplier[i]->setValue(multiplier[i]->getValue() + 0.01f * inc); + } + + // Raise event (only for first multiplier because associated event concerns all multipliers) + adjusterChanged(multiplier[0], multiplier[0]->getValue()); // Value isn't used +} + +void LocallabCBDL::lumaneutralPressed() +{ + for (int i = 0; i < 6; i++) { + multiplier[i]->setValue(1.0); + } + + // Raise event (only for first multiplier because associated event concerns all multipliers) + adjusterChanged(multiplier[0], multiplier[0]->getValue()); // Value isn't used +} + +void LocallabCBDL::lumacontrastPlusPressed() +{ + for (int i = 0; i < 6; i++) { + float inc = (5 - i); + multiplier[i]->setValue(multiplier[i]->getValue() + 0.01f * inc); + } + + // Raise event (only for first multiplier because associated event concerns all multipliers) + adjusterChanged(multiplier[0], multiplier[0]->getValue()); // Value isn't used +} + +/* ==== LocallabDenoise ==== */ +LocallabDenoise::LocallabDenoise(): + LocallabTool(this, "Locallab Denoise", M("TP_LOCALLAB_DENOIS"), true, MaskNone), + + // Denoise specific widgets + noiselumf0(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINEZERO"), MINCHRO, MAXCHRO, 1, 0))), + noiselumf(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINE"), MINCHRO, MAXCHRO, 1, 0))), + noiselumf2(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINETWO"), MINCHRO, MAXCHRO, 1, 0))), + noiselumc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMCOARSE"), MINCHRO, MAXCHROCC, 1, 0))), + noiselumdetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMDETAIL"), 0, 100, 1, 0))), + noiselequal(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELEQUAL"), -2, 10, 1, 7, Gtk::manage(new RTImage("circle-white-small.png")), Gtk::manage(new RTImage("circle-black-small.png"))))), + noisechrof(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROFINE"), MINCHRO, MAXCHRO, 1, 0))), + noisechroc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROCOARSE"), MINCHRO, MAXCHROCC, 1, 0))), + noisechrodetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHRODETAIL"), 0, 100, 1, 0))), + adjblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ADJ"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-small.png")), Gtk::manage(new RTImage("circle-red-small.png"))))), + bilateral(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BILATERAL"), 0, 100, 1, 0))), + sensiden(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIDEN"), 0, 100, 1, 20))) +{ + const bool showtooltip = options.showtooltip; + + noiselumf0->setAdjusterListener(this); + + noiselumf->setAdjusterListener(this); + + noiselumf2->setAdjusterListener(this); + + if (showtooltip) { + noiselumc->set_tooltip_text(M("TP_LOCALLAB_NOISECHROC_TOOLTIP")); + } + + noiselumc->setAdjusterListener(this); + + noiselumdetail->setAdjusterListener(this); + + noiselequal->setAdjusterListener(this); + + noisechrof->setAdjusterListener(this); + + if (showtooltip) { + noisechroc->set_tooltip_text(M("TP_LOCALLAB_NOISECHROC_TOOLTIP")); + } + + noisechroc->setAdjusterListener(this); + + noisechrodetail->setAdjusterListener(this); + + adjblur->setAdjusterListener(this); + + bilateral->setAdjusterListener(this); + + sensiden->setAdjusterListener(this); + + Gtk::Frame* const wavFrame = Gtk::manage(new Gtk::Frame()); + ToolParamBlock* const wavBox = Gtk::manage(new ToolParamBlock()); + wavBox->pack_start(*noiselumf0); + wavBox->pack_start(*noiselumf); + wavBox->pack_start(*noiselumf2); + wavBox->pack_start(*noiselumc); + wavBox->pack_start(*noiselumdetail); + wavBox->pack_start(*noiselequal); + wavBox->pack_start(*noisechrof); + wavBox->pack_start(*noisechroc); + // wavBox->pack_start(*noisechrodetail); // Uncomment this line to use the noisechrodetail adjuster + wavBox->pack_start(*adjblur); + wavFrame->add(*wavBox); + pack_start(*wavFrame); + pack_start(*bilateral); + pack_start(*sensiden); +} + +void LocallabDenoise::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) +{ + // Disable all listeners + disableListener(); + + // Update GUI to selected spot value + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + spotName = pp->locallab.spots.at(index).name; // Update spot name according to selected spot + + exp->setEnabled(pp->locallab.spots.at(index).expdenoi); + noiselumf0->setValue(pp->locallab.spots.at(index).noiselumf0); + noiselumf->setValue(pp->locallab.spots.at(index).noiselumf); + noiselumf2->setValue(pp->locallab.spots.at(index).noiselumf2); + noiselumc->setValue(pp->locallab.spots.at(index).noiselumc); + noiselumdetail->setValue(pp->locallab.spots.at(index).noiselumdetail); + noiselequal->setValue(pp->locallab.spots.at(index).noiselequal); + noisechrof->setValue(pp->locallab.spots.at(index).noisechrof); + noisechroc->setValue(pp->locallab.spots.at(index).noisechroc); + noisechrodetail->setValue(pp->locallab.spots.at(index).noisechrodetail); + adjblur->setValue(pp->locallab.spots.at(index).adjblur); + bilateral->setValue(pp->locallab.spots.at(index).bilateral); + sensiden->setValue(pp->locallab.spots.at(index).sensiden); + } + + // Enable all listeners + enableListener(); + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabDenoise::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) +{ + const int index = pp->locallab.selspot; + + if (index < (int)pp->locallab.spots.size()) { + pp->locallab.spots.at(index).expdenoi = exp->getEnabled(); + pp->locallab.spots.at(index).noiselumf0 = noiselumf0->getIntValue(); + pp->locallab.spots.at(index).noiselumf = noiselumf->getIntValue(); + pp->locallab.spots.at(index).noiselumf2 = noiselumf2->getIntValue(); + pp->locallab.spots.at(index).noiselumc = noiselumc->getIntValue(); + pp->locallab.spots.at(index).noiselumdetail = noiselumdetail->getIntValue(); + pp->locallab.spots.at(index).noiselequal = noiselequal->getIntValue(); + pp->locallab.spots.at(index).noisechrof = noisechrof->getIntValue(); + pp->locallab.spots.at(index).noisechroc = noisechroc->getIntValue(); + pp->locallab.spots.at(index).noisechrodetail = noisechrodetail->getIntValue(); + pp->locallab.spots.at(index).adjblur = adjblur->getIntValue(); + pp->locallab.spots.at(index).bilateral = bilateral->getIntValue(); + pp->locallab.spots.at(index).sensiden = sensiden->getIntValue(); + } + + // Note: No need to manage pedited as batch mode is deactivated for Locallab +} + +void LocallabDenoise::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) +{ + // TODO +} + +void LocallabDenoise::adjusterChanged(Adjuster* a, double newval) +{ + if (isLocActivated && exp->getEnabled()) { + if (a == noiselumf0) { + if (listener) { + listener->panelChanged(Evlocallabnoiselumf0, + noiselumf0->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == noiselumf) { + if (listener) { + listener->panelChanged(Evlocallabnoiselumf, + noiselumf->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == noiselumf2) { + if (listener) { + listener->panelChanged(Evlocallabnoiselumf2, + noiselumf2->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == noiselumc) { + if (listener) { + listener->panelChanged(Evlocallabnoiselumc, + noiselumc->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == noiselumdetail) { + if (listener) { + listener->panelChanged(Evlocallabnoiselumdetail, + noiselumdetail->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == noiselequal) { + if (listener) { + listener->panelChanged(Evlocallabnoiselequal, + noiselequal->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == noisechrof) { + if (listener) { + listener->panelChanged(Evlocallabnoisechrof, + noisechrof->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == noisechroc) { + if (listener) { + listener->panelChanged(Evlocallabnoisechroc, + noisechroc->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == noisechrodetail) { + if (listener) { + listener->panelChanged(Evlocallabnoisechrodetail, + noisechrodetail->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == adjblur) { + if (listener) { + listener->panelChanged(Evlocallabadjblur, + adjblur->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == bilateral) { + if (listener) { + listener->panelChanged(Evlocallabbilateral, + bilateral->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + + if (a == sensiden) { + if (listener) { + listener->panelChanged(Evlocallabsensiden, + sensiden->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} + +void LocallabDenoise::enabledChanged() +{ + if (isLocActivated) { + if (listener) { + if (exp->getEnabled()) { + listener->panelChanged(EvLocenadenoi, + M("GENERAL_ENABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } else { + listener->panelChanged(EvLocenadenoi, + M("GENERAL_DISABLED") + " (" + escapeHtmlChars(spotName) + ")"); + } + } + } +} diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 340d9917b..89c5047d4 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -139,6 +139,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren raw_ca_autocorrect = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_AUTO"))); raw_caredblue = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_CAREDBLUE"))); raw_ca_avoid_colourshift = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_AVOIDCOLORSHIFT"))); + //--- + filmNegative = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_FILMNEGATIVE")) ); Gtk::VBox* vboxes[9]; Gtk::HSeparator* hseps[9]; @@ -237,6 +239,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren vboxes[8]->pack_start (*raw_dcb_enhance, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*raw_lmmse_iterations, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); + vboxes[8]->pack_start (*raw_linenoise, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*raw_greenthresh, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*raw_hotpix_filt, Gtk::PACK_SHRINK, 2); vboxes[8]->pack_start (*raw_deadpix_filt, Gtk::PACK_SHRINK, 2);