diff --git a/rtdata/languages/default b/rtdata/languages/default index 1c6b2a593..62701b85f 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -393,6 +393,7 @@ HISTORY_MSG_142;ES - Iterations HISTORY_MSG_143;ES - Quantity HISTORY_MSG_144;Microcontrast - Quantity HISTORY_MSG_145;Microcontrast - Uniformity +HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold HISTORY_MSG_146;Edge sharpening HISTORY_MSG_147;ES - Luminance only HISTORY_MSG_148;Microcontrast @@ -1950,6 +1951,7 @@ TP_SHARPENING_RLD_ITERATIONS;Iterations TP_SHARPENING_THRESHOLD;Threshold TP_SHARPENING_USM;Unsharp Mask TP_SHARPENMICRO_AMOUNT;Quantity +TP_SHARPENMICRO_CONTRAST;Contrast threshold TP_SHARPENMICRO_LABEL;Microcontrast TP_SHARPENMICRO_MATRIX;3×3 matrix instead of 5×5 TP_SHARPENMICRO_UNIFORMITY;Uniformity diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 3c455b03e..3cdc613df 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -23,7 +23,8 @@ #include "rt_math.h" #include "sleef.c" #include "opthelper.h" - +#define BENCHMARK +#include "StopWatch.h" using namespace std; namespace rtengine @@ -572,12 +573,13 @@ void ImProcFunctions::MLsharpen (LabImage* lab) //! \param luminance : Luminance channel of image void ImProcFunctions::MLmicrocontrast(float** luminance, int W, int H) { - if (!params->sharpenMicro.enabled) { + if (!params->sharpenMicro.enabled || params->sharpenMicro.contrast == 100) { return; } - +BENCHFUN const int k = params->sharpenMicro.matrix ? 1 : 2; - + const float contrastThreshold = params->sharpenMicro.contrast / 100; + const float contrastFactor = contrastThreshold == 0.f ? 0.f : 1.f / contrastThreshold; // k=2 matrix 5x5 k=1 matrix 3x3 const int width = W, height = H; const float uniform = params->sharpenMicro.uniformity; //between 0 to 100 @@ -619,8 +621,8 @@ void ImProcFunctions::MLmicrocontrast(float** luminance, int W, int H) const float Cont5[11] = {1.0f, 1.1f, 1.2f, 1.25f, 1.3f, 1.4f, 1.45f, 1.50f, 1.6f, 1.65f, 1.80f}; const float s = amount; - const float sqrt2 = sqrt(2.0); - const float sqrt1d25 = sqrt(1.25); + constexpr float sqrt2 = sqrt(2.0); + constexpr float sqrt1d25 = sqrt(1.25); float *LM = new float[width * height]; //allocation for Luminance #ifdef _OPENMP @@ -652,6 +654,9 @@ void ImProcFunctions::MLmicrocontrast(float** luminance, int W, int H) + SQR(LM[offset + 2] - LM[offset - 2]) + SQR(LM[offset + 2 * width] - LM[offset - 2 * width])) * 0.0625f; //for 5x5 contrast = std::min(contrast, 1.f); + float blend = 0.f; + if(contrast <= contrastThreshold) + blend = sqrt((contrastThreshold - contrast) * contrastFactor); //matrix 5x5 float temp = v + 4.f *( v * (s + sqrt2 * s)); //begin 3x3 @@ -675,13 +680,12 @@ void ImProcFunctions::MLmicrocontrast(float** luminance, int W, int H) temp = std::max(temp, 0.f); - for(int row = j + k, n = SQR(2*k+1) - 1; row >= j - k; row--) { - for(int offset2 = row * width + i + k; offset2 >= row * width + i - k; offset2--) { + for(int row = j - k; row <= j + k; ++row) { + for(int offset2 = row * width + i - k; offset2 <= row * width + i + k; ++offset2) { if((LM[offset2] - temp) * (v - LM[offset2]) > 0.f) { temp = intp(0.75f, temp, LM[offset2]); goto breakout; } - n--; } } breakout: @@ -751,7 +755,7 @@ void ImProcFunctions::MLmicrocontrast(float** luminance, int W, int H) } else { temp = 0.f; } - luminance[j][i] *= (temp * temp2 + 1.f); + luminance[j][i] = intp(blend, luminance[j][i], luminance[j][i] * (temp * temp2 + 1.f)); } else { float temp4 = LM[offset] / tempL; // @@ -802,7 +806,7 @@ void ImProcFunctions::MLmicrocontrast(float** luminance, int W, int H) } else { temp = 0.f; } - luminance[j][i] /= (temp * temp4 + 1.f); + luminance[j][i] = intp(blend, luminance[j][i], luminance[j][i] / (temp * temp4 + 1.f)); } } } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 276750786..db671a8ab 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -1073,6 +1073,7 @@ SharpenMicroParams::SharpenMicroParams() : enabled(false), matrix(false), amount(20.0), + contrast(20.0), uniformity(50.0) { } @@ -1083,6 +1084,7 @@ bool SharpenMicroParams::operator ==(const SharpenMicroParams& other) const enabled == other.enabled && matrix == other.matrix && amount == other.amount + && contrast == other.contrast && uniformity == other.uniformity; } @@ -2885,6 +2887,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->sharpenMicro.enabled, "SharpenMicro", "Enabled", sharpenMicro.enabled, keyFile); saveToKeyfile(!pedited || pedited->sharpenMicro.matrix, "SharpenMicro", "Matrix", sharpenMicro.matrix, keyFile); saveToKeyfile(!pedited || pedited->sharpenMicro.amount, "SharpenMicro", "Strength", sharpenMicro.amount, keyFile); + saveToKeyfile(!pedited || pedited->sharpenMicro.contrast, "SharpenMicro", "Contrast", sharpenMicro.contrast, keyFile); saveToKeyfile(!pedited || pedited->sharpenMicro.uniformity, "SharpenMicro", "Uniformity", sharpenMicro.uniformity, keyFile); // WB @@ -3710,6 +3713,14 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "SharpenMicro", "Enabled", pedited, sharpenMicro.enabled, pedited->sharpenMicro.enabled); assignFromKeyfile(keyFile, "SharpenMicro", "Matrix", pedited, sharpenMicro.matrix, pedited->sharpenMicro.matrix); assignFromKeyfile(keyFile, "SharpenMicro", "Strength", pedited, sharpenMicro.amount, pedited->sharpenMicro.amount); + if (ppVersion >= 334) { + assignFromKeyfile(keyFile, "SharpenMicro", "Contrast", pedited, sharpenMicro.contrast, pedited->sharpenMicro.contrast); + } else { + sharpenMicro.contrast = 0; + if (pedited) { + pedited->sharpenMicro.contrast = true; + } + } assignFromKeyfile(keyFile, "SharpenMicro", "Uniformity", pedited, sharpenMicro.uniformity, pedited->sharpenMicro.uniformity); } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 5e7b9ff2d..bc2a9d97c 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -509,6 +509,7 @@ struct SharpenMicroParams { bool enabled; bool matrix; double amount; + double contrast; double uniformity; SharpenMicroParams(); diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 49eefc794..e0e0b20dd 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -134,6 +134,7 @@ enum { ADDSET_LOCALCONTRAST_DARKNESS, ADDSET_LOCALCONTRAST_LIGHTNESS, ADDSET_FATTAL_ANCHOR, + ADDSET_SHARPENMICRO_CONTRAST, ADDSET_PARAM_NUM // THIS IS USED AS A DELIMITER!! }; diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index d3c3fb4c6..99c7a089d 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -149,7 +149,7 @@ void BatchToolPanelCoordinator::initSession () sharpening->setAdjusterBehavior (false, false, false, false, false, false); prsharpening->setAdjusterBehavior (false, false, false, false, false, false); sharpenEdge->setAdjusterBehavior (false, false); - sharpenMicro->setAdjusterBehavior (false, false); + sharpenMicro->setAdjusterBehavior (false, false, false); icm->setAdjusterBehavior (false, false); epd->setAdjusterBehavior (false, false, false, false, false); fattal->setAdjusterBehavior (false, false, false); @@ -196,7 +196,7 @@ void BatchToolPanelCoordinator::initSession () localContrast->setAdjusterBehavior(options.baBehav[ADDSET_LOCALCONTRAST_RADIUS], options.baBehav[ADDSET_LOCALCONTRAST_AMOUNT], options.baBehav[ADDSET_LOCALCONTRAST_DARKNESS], options.baBehav[ADDSET_LOCALCONTRAST_LIGHTNESS]); sharpenEdge->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT], options.baBehav[ADDSET_SHARPENEDGE_PASS]); - sharpenMicro->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT], options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]); + sharpenMicro->setAdjusterBehavior (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT], options.baBehav[ADDSET_SHARPENMICRO_CONTRAST], options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]); icm->setAdjusterBehavior (options.baBehav[ADDSET_FREE_OUPUT_GAMMA], options.baBehav[ADDSET_FREE_OUTPUT_SLOPE]); // colortoning->setAdjusterBehavior (options.baBehav[ADDSET_COLORTONING_SPLIT], options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD], options.baBehav[ADDSET_COLORTONING_SATOPACITY], options.baBehav[ADDSET_COLORTONING_STRPROTECT], options.baBehav[ADDSET_COLORTONING_BALANCE]); colortoning->setAdjusterBehavior (options.baBehav[ADDSET_COLORTONING_SPLIT], options.baBehav[ADDSET_COLORTONING_SATTHRESHOLD], options.baBehav[ADDSET_COLORTONING_SATOPACITY], options.baBehav[ADDSET_COLORTONING_STRENGTH], options.baBehav[ADDSET_COLORTONING_BALANCE]); @@ -244,6 +244,7 @@ void BatchToolPanelCoordinator::initSession () if (options.baBehav[ADDSET_SHARP_HALOCTRL]) { pparams.sharpening.halocontrol_amount = pparams.prsharpening.halocontrol_amount = 0; } if (options.baBehav[ADDSET_SHARPENEDGE_AMOUNT]) { pparams.sharpenEdge.amount = 0; } if (options.baBehav[ADDSET_SHARPENMICRO_AMOUNT]) { pparams.sharpenMicro.amount = 0; } + if (options.baBehav[ADDSET_SHARPENMICRO_CONTRAST]) { pparams.sharpenMicro.contrast = 0; } if (options.baBehav[ADDSET_SHARPENEDGE_PASS]) { pparams.sharpenEdge.passes = 0; } if (options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY]) { pparams.sharpenMicro.uniformity = 0; } if (options.baBehav[ADDSET_CHMIXER]) for (int i = 0; i < 3; i++) { pparams.chmixer.red[i] = pparams.chmixer.green[i] = pparams.chmixer.blue[i] = 0; } diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 391228c9b..0d3ee8f22 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -175,6 +175,7 @@ void ParamsEdited::set (bool v) sharpenEdge.threechannels = v; sharpenMicro.enabled = v; sharpenMicro.matrix = v; + sharpenMicro.contrast = v; sharpenMicro.amount = v; sharpenMicro.uniformity = v; vibrance.enabled = v; @@ -691,6 +692,7 @@ void ParamsEdited::initFrom (const std::vector sharpenMicro.enabled = sharpenMicro.enabled && p.sharpenMicro.enabled == other.sharpenMicro.enabled; sharpenMicro.matrix = sharpenMicro.matrix && p.sharpenMicro.matrix == other.sharpenMicro.matrix; sharpenMicro.amount = sharpenMicro.amount && p.sharpenMicro.amount == other.sharpenMicro.amount; + sharpenMicro.contrast = sharpenMicro.contrast && p.sharpenMicro.contrast == other.sharpenMicro.contrast; sharpenMicro.uniformity = sharpenMicro.uniformity && p.sharpenMicro.uniformity == other.sharpenMicro.uniformity; sharpening.enabled = sharpening.enabled && p.sharpening.enabled == other.sharpening.enabled; sharpening.radius = sharpening.radius && p.sharpening.radius == other.sharpening.radius; @@ -1564,6 +1566,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.sharpenMicro.amount = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_AMOUNT] ? toEdit.sharpenMicro.amount + mods.sharpenMicro.amount : mods.sharpenMicro.amount; } + if (sharpenMicro.contrast) { + toEdit.sharpenMicro.contrast = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_CONTRAST] ? toEdit.sharpenMicro.contrast + mods.sharpenMicro.contrast : mods.sharpenMicro.contrast; + } + if (sharpenMicro.uniformity) { toEdit.sharpenMicro.uniformity = dontforceSet && options.baBehav[ADDSET_SHARPENMICRO_UNIFORMITY] ? toEdit.sharpenMicro.uniformity + mods.sharpenMicro.uniformity : mods.sharpenMicro.uniformity; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index e28a83a6f..e11eb1814 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -194,6 +194,7 @@ public : bool enabled; bool matrix; bool amount; + bool contrast; bool uniformity; }; diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index 1265d9969..e9f7ad60e 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -1,11 +1,13 @@ #pragma once // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes -#define PPVERSION 333 +#define PPVERSION 334 #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified /* Log of version changes + 334 2018-05-13 + new contrast threshold adjuster in Microcontrast tool 333 2018-04-26 new Shadows/Highlights tool 332 2018-04-18 diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 2c5154942..db2deada7 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -248,6 +248,7 @@ Gtk::Widget* Preferences::getBatchProcPanel () mi = behModel->append (); mi->set_value (behavColumns.label, M ("TP_SHARPENMICRO_LABEL")); appendBehavList (mi, M ("TP_SHARPENMICRO_AMOUNT"), ADDSET_SHARPENMICRO_AMOUNT, false); + appendBehavList (mi, M ("TP_SHARPENMICRO_CONTRAST"), ADDSET_SHARPENMICRO_CONTRAST, false); appendBehavList (mi, M ("TP_SHARPENMICRO_UNIFORMITY"), ADDSET_SHARPENMICRO_UNIFORMITY, false); mi = behModel->append (); diff --git a/rtgui/sharpenmicro.cc b/rtgui/sharpenmicro.cc index 871e0d38b..ff1447cb3 100644 --- a/rtgui/sharpenmicro.cc +++ b/rtgui/sharpenmicro.cc @@ -16,10 +16,11 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include +#include #include "sharpenmicro.h" #include "guiutils.h" -#include -#include +#include "eventmapper.h" using namespace rtengine; using namespace rtengine::procparams; @@ -28,6 +29,9 @@ using namespace rtengine::procparams; SharpenMicro::SharpenMicro () : FoldableToolPanel(this, "sharpenmicro", M("TP_SHARPENMICRO_LABEL"), true, true) { + auto m = ProcEventMapper::getInstance(); + EvSharpenMicroContrast = m->newEvent(SHARPENING, "HISTORY_MSG_MICROCONTRAST_CONTRAST"); + amount = Gtk::manage(new Adjuster (M("TP_SHARPENMICRO_AMOUNT"), 0, 100, 1, 20)); amount->setAdjusterListener (this); @@ -36,6 +40,16 @@ SharpenMicro::SharpenMicro () : FoldableToolPanel(this, "sharpenmicro", M("TP_SH } amount->show(); + + contrast = Gtk::manage(new Adjuster (M("TP_SHARPENMICRO_CONTRAST"), 0, 100, 1, 20)); + contrast->setAdjusterListener (this); + + if (contrast->delay < options.adjusterMaxDelay) { + contrast->delay = options.adjusterMaxDelay; + } + + contrast->show(); + uniformity = Gtk::manage(new Adjuster (M("TP_SHARPENMICRO_UNIFORMITY"), 0, 100, 10, 50)); uniformity->setAdjusterListener (this); @@ -51,6 +65,7 @@ SharpenMicro::SharpenMicro () : FoldableToolPanel(this, "sharpenmicro", M("TP_SH matrix->show (); pack_start( *amount, Gtk::PACK_SHRINK, 0); + pack_start( *contrast, Gtk::PACK_SHRINK, 0); pack_start( *uniformity, Gtk::PACK_SHRINK, 0); matrixconn = matrix->signal_toggled().connect( sigc::mem_fun(*this, &SharpenMicro::matrix_toggled) ); @@ -64,6 +79,7 @@ void SharpenMicro::read(const ProcParams* pp, const ParamsEdited* pedited) set_inconsistent (multiImage && !pedited->sharpenMicro.enabled); matrix->set_inconsistent (!pedited->sharpenMicro.matrix); amount->setEditedState (pedited->sharpenMicro.amount ? Edited : UnEdited); + contrast->setEditedState (pedited->sharpenMicro.contrast ? Edited : UnEdited); uniformity->setEditedState (pedited->sharpenMicro.uniformity ? Edited : UnEdited); } @@ -75,6 +91,7 @@ void SharpenMicro::read(const ProcParams* pp, const ParamsEdited* pedited) lastmatrix = pp->sharpenMicro.matrix; amount->setValue (pp->sharpenMicro.amount); + contrast->setValue (pp->sharpenMicro.contrast); uniformity->setValue (pp->sharpenMicro.uniformity); enableListener (); @@ -85,12 +102,14 @@ void SharpenMicro::write( ProcParams* pp, ParamsEdited* pedited) pp->sharpenMicro.enabled = getEnabled(); pp->sharpenMicro.matrix = matrix->get_active (); pp->sharpenMicro.amount = amount->getValue (); + pp->sharpenMicro.contrast = contrast->getValue (); pp->sharpenMicro.uniformity = uniformity->getValue (); if (pedited) { pedited->sharpenMicro.enabled = !get_inconsistent(); pedited->sharpenMicro.matrix = !matrix->get_inconsistent(); pedited->sharpenMicro.amount = amount->getEditedState (); + pedited->sharpenMicro.contrast = contrast->getEditedState (); pedited->sharpenMicro.uniformity = uniformity->getEditedState (); } } @@ -139,9 +158,11 @@ void SharpenMicro::adjusterChanged (Adjuster* a, double newval) Glib::ustring value = a->getTextValue(); if (a == amount) { - listener->panelChanged (EvSharpenMicroAmount, value ); + listener->panelChanged (EvSharpenMicroAmount, value); + } else if (a == contrast) { + listener->panelChanged (EvSharpenMicroContrast, value); } else if (a == uniformity) { - listener->panelChanged (EvSharpenMicroUniformity, value ); + listener->panelChanged (EvSharpenMicroUniformity, value); } } } @@ -149,31 +170,37 @@ void SharpenMicro::adjusterChanged (Adjuster* a, double newval) void SharpenMicro::setBatchMode(bool batchMode) { amount->showEditedCB (); + contrast->showEditedCB (); uniformity->showEditedCB (); } void SharpenMicro::setDefaults(const ProcParams* defParams, const ParamsEdited* pedited) { amount->setDefault (defParams->sharpenMicro.amount); + contrast->setDefault (defParams->sharpenMicro.contrast); uniformity->setDefault (defParams->sharpenMicro.uniformity); if (pedited) { amount->setDefaultEditedState (pedited->sharpenMicro.amount ? Edited : UnEdited); + contrast->setDefaultEditedState (pedited->sharpenMicro.contrast ? Edited : UnEdited); uniformity->setDefaultEditedState (pedited->sharpenMicro.uniformity ? Edited : UnEdited); } else { amount->setDefaultEditedState (Irrelevant); + contrast->setDefaultEditedState (Irrelevant); uniformity->setDefaultEditedState (Irrelevant); } } -void SharpenMicro::setAdjusterBehavior (bool amountadd, bool uniformityadd ) +void SharpenMicro::setAdjusterBehavior (bool amountadd, bool contrastadd, bool uniformityadd) { amount->setAddMode (amountadd); + contrast->setAddMode (contrastadd); uniformity->setAddMode (uniformityadd); } void SharpenMicro::trimValues (ProcParams* pp) { amount->trimValue (pp->sharpenMicro.amount); + contrast->trimValue (pp->sharpenMicro.contrast); uniformity->trimValue (pp->sharpenMicro.uniformity); } diff --git a/rtgui/sharpenmicro.h b/rtgui/sharpenmicro.h index 03a75eaa5..e1fc0d7e0 100644 --- a/rtgui/sharpenmicro.h +++ b/rtgui/sharpenmicro.h @@ -36,6 +36,9 @@ protected: Gtk::CheckButton* matrix; Adjuster* amount; Adjuster* uniformity; + Adjuster* contrast; + + rtengine::ProcEvent EvSharpenMicroContrast; sigc::connection matrixconn; bool lastmatrix; @@ -49,7 +52,7 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void setBatchMode (bool batchMode); void trimValues (rtengine::procparams::ProcParams* pp); - void setAdjusterBehavior (bool amountadd, bool uniformityadd ); + void setAdjusterBehavior (bool amountadd, bool contrastadd, bool uniformityadd); void adjusterChanged (Adjuster* a, double newval); void enabledChanged ();