From 5162484517b9711dc4e274f8bae8f514bc617f0b Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 8 Dec 2018 21:57:56 +0100 Subject: [PATCH 01/11] First quick&dirty version of flat region blur, #5075 --- rtdata/languages/default | 2 ++ rtengine/ipsharpen.cc | 42 ++++++++++++++++++++++++++++++++++++++-- rtengine/procparams.cc | 4 ++++ rtengine/procparams.h | 1 + rtgui/paramsedited.cc | 6 ++++++ rtgui/paramsedited.h | 1 + rtgui/sharpening.cc | 20 +++++++++++++++++-- rtgui/sharpening.h | 2 ++ 8 files changed, 74 insertions(+), 4 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index da79ec3ac..ae75bc343 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -774,6 +774,7 @@ HISTORY_MSG_RAWCACORR_AUTOIT;Raw CA Correction - Iterations HISTORY_MSG_RAWCACORR_COLORSHIFT;Raw CA Correction - Avoid color shift HISTORY_MSG_RAW_BORDER;Raw border HISTORY_MSG_RESIZE_ALLOWUPSCALING;Resize - Allow upscaling +HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light @@ -2034,6 +2035,7 @@ TP_SHARPENEDGE_LABEL;Edges TP_SHARPENEDGE_PASSES;Iterations TP_SHARPENEDGE_THREE;Luminance only TP_SHARPENING_AMOUNT;Amount +TP_SHARPENING_BLUR;Blur radius TP_SHARPENING_CONTRAST;Contrast threshold TP_SHARPENING_EDRADIUS;Radius TP_SHARPENING_EDTOLERANCE;Edge tolerance diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 321dd635f..002337b2f 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -159,7 +159,7 @@ extern const Settings* settings; void ImProcFunctions::deconvsharpening (float** luminance, float** tmp, int W, int H, const SharpeningParams &sharpenParam) { - if (sharpenParam.deconvamount < 1) { + if (sharpenParam.deconvamount == 0) { return; } BENCHFUN @@ -178,7 +178,14 @@ BENCHFUN JaggedArray blend(W, H); float contrast = sharpenParam.contrast / 100.f; buildBlendMask(luminance, blend, W, H, contrast, sharpenParam.deconvamount / 100.f); + JaggedArray blur(W, H); + if(sharpenParam.blurradius > 0) { + #pragma omp parallel + { + gaussianBlur(tmpI, blur, W, H, sharpenParam.blurradius); + } + } const float damping = sharpenParam.deconvdamping / 5.0; const bool needdamp = sharpenParam.deconvdamping > 0; const double sigma = sharpenParam.deconvradius / scale; @@ -208,6 +215,17 @@ BENCHFUN luminance[i][j] = intp(blend[i][j], max(tmpI[i][j], 0.0f), luminance[i][j]); } } + + if(sharpenParam.blurradius > 0) { +#ifdef _OPENMP + #pragma omp for +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + luminance[i][j] = intp(blend[i][j], luminance[i][j], max(blur[i][j], 0.0f)); + } + } + } } // end parallel } @@ -224,7 +242,7 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); float contrast = sharpenParam.contrast / 100.f; - buildBlendMask(lab->L, blend, W, H, contrast, sharpenParam.method == "rld" ? sharpenParam.deconvamount / 100.f : 1.f); + buildBlendMask(lab->L, blend, W, H, contrast, sharpenParam.method == "rld" ? 1.f : 1.f); #ifdef _OPENMP #pragma omp parallel for #endif @@ -256,6 +274,15 @@ BENCHFUN } } + JaggedArray blur(W, H); + + if(sharpenParam.blurradius > 0) { + #pragma omp parallel + { + gaussianBlur(lab->L, blur, W, H, sharpenParam.blurradius); + } + } + // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); float contrast = sharpenParam.contrast / 100.f; @@ -322,6 +349,17 @@ BENCHFUN delete [] b3; } + if(sharpenParam.blurradius > 0) { +#ifdef _OPENMP + #pragma omp parallel for +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + lab->L[i][j] = intp(blend[i][j], lab->L[i][j], max(blur[i][j], 0.0f)); + } + } + } + } // To the extent possible under law, Manuel Llorens diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 9addfdce9..7ce7b8608 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -1079,6 +1079,7 @@ void ColorToningParams::getCurves(ColorGradientCurve& colorCurveLUT, OpacityCurv SharpeningParams::SharpeningParams() : enabled(false), contrast(20.0), + blurradius(0.2), radius(0.5), amount(200), threshold(20, 80, 2000, 1200, false), @@ -1100,6 +1101,7 @@ bool SharpeningParams::operator ==(const SharpeningParams& other) const return enabled == other.enabled && contrast == other.contrast + && blurradius == other.blurradius && radius == other.radius && amount == other.amount && threshold == other.threshold @@ -3022,6 +3024,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->sharpening.contrast, "Sharpening", "Contrast", sharpening.contrast, keyFile); saveToKeyfile(!pedited || pedited->sharpening.method, "Sharpening", "Method", sharpening.method, keyFile); saveToKeyfile(!pedited || pedited->sharpening.radius, "Sharpening", "Radius", sharpening.radius, keyFile); + saveToKeyfile(!pedited || pedited->sharpening.blurradius, "Sharpening", "BlurRadius", sharpening.blurradius, keyFile); saveToKeyfile(!pedited || pedited->sharpening.amount, "Sharpening", "Amount", sharpening.amount, keyFile); saveToKeyfile(!pedited || pedited->sharpening.threshold, "Sharpening", "Threshold", sharpening.threshold.toVector(), keyFile); saveToKeyfile(!pedited || pedited->sharpening.edgesonly, "Sharpening", "OnlyEdges", sharpening.edgesonly, keyFile); @@ -3908,6 +3911,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } } assignFromKeyfile(keyFile, "Sharpening", "Radius", pedited, sharpening.radius, pedited->sharpening.radius); + assignFromKeyfile(keyFile, "Sharpening", "BlurRadius", pedited, sharpening.blurradius, pedited->sharpening.blurradius); assignFromKeyfile(keyFile, "Sharpening", "Amount", pedited, sharpening.amount, pedited->sharpening.amount); if (keyFile.has_key("Sharpening", "Threshold")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 79f3fc7ec..d1b70b9c2 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -493,6 +493,7 @@ struct ColorToningParams { struct SharpeningParams { bool enabled; double contrast; + double blurradius; double radius; int amount; Threshold threshold; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 27b06c4f7..7f44c7738 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -147,6 +147,7 @@ void ParamsEdited::set(bool v) sharpening.enabled = v; sharpening.contrast = v; sharpening.radius = v; + sharpening.blurradius = v; sharpening.amount = v; sharpening.threshold = v; sharpening.edgesonly = v; @@ -719,6 +720,7 @@ void ParamsEdited::initFrom(const std::vector& sharpening.enabled = sharpening.enabled && p.sharpening.enabled == other.sharpening.enabled; sharpening.contrast = sharpening.contrast && p.sharpening.contrast == other.sharpening.contrast; sharpening.radius = sharpening.radius && p.sharpening.radius == other.sharpening.radius; + sharpening.blurradius = sharpening.blurradius && p.sharpening.blurradius == other.sharpening.blurradius; sharpening.amount = sharpening.amount && p.sharpening.amount == other.sharpening.amount; sharpening.threshold = sharpening.threshold && p.sharpening.threshold == other.sharpening.threshold; sharpening.edgesonly = sharpening.edgesonly && p.sharpening.edgesonly == other.sharpening.edgesonly; @@ -1639,6 +1641,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.sharpening.radius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.radius + mods.sharpening.radius : mods.sharpening.radius; } + if (sharpening.blurradius) { + toEdit.sharpening.blurradius = dontforceSet && options.baBehav[ADDSET_SHARP_RADIUS] ? toEdit.sharpening.blurradius + mods.sharpening.blurradius : mods.sharpening.blurradius; + } + if (sharpening.amount) { toEdit.sharpening.amount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.sharpening.amount + mods.sharpening.amount : mods.sharpening.amount; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 7b4b9c061..3e77fcf56 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -209,6 +209,7 @@ class SharpeningParamsEdited public: bool enabled; bool contrast; + bool blurradius; bool radius; bool amount; bool threshold; diff --git a/rtgui/sharpening.cc b/rtgui/sharpening.cc index 3614594ea..8a7b8e591 100644 --- a/rtgui/sharpening.cc +++ b/rtgui/sharpening.cc @@ -27,6 +27,7 @@ Sharpening::Sharpening () : FoldableToolPanel(this, "sharpening", M("TP_SHARPENI { auto m = ProcEventMapper::getInstance(); EvSharpenContrast = m->newEvent(SHARPENING, "HISTORY_MSG_SHARPENING_CONTRAST"); + EvSharpenBlur = m->newEvent(SHARPENING, "HISTORY_MSG_SHARPENING_BLUR"); Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); hb->show (); @@ -34,6 +35,10 @@ Sharpening::Sharpening () : FoldableToolPanel(this, "sharpening", M("TP_SHARPENI contrast->setAdjusterListener (this); pack_start(*contrast); contrast->show(); + blur = Gtk::manage(new Adjuster (M("TP_SHARPENING_BLUR"), 0.2, 2.0, 0.05, 0.2)); + blur->setAdjusterListener (this); + pack_start(*blur); + blur->show(); Gtk::Label* ml = Gtk::manage (new Gtk::Label (M("TP_SHARPENING_METHOD") + ":")); ml->show (); @@ -152,7 +157,8 @@ void Sharpening::read (const ProcParams* pp, const ParamsEdited* pedited) disableListener (); if (pedited) { - contrast->setEditedState (pedited->sharpening.contrast ? Edited : UnEdited); + contrast->setEditedState (pedited->sharpening.contrast ? Edited : UnEdited); + blur->setEditedState (pedited->sharpening.blurradius ? Edited : UnEdited); amount->setEditedState (pedited->sharpening.amount ? Edited : UnEdited); radius->setEditedState (pedited->sharpening.radius ? Edited : UnEdited); threshold->setEditedState (pedited->sharpening.threshold ? Edited : UnEdited); @@ -182,6 +188,7 @@ void Sharpening::read (const ProcParams* pp, const ParamsEdited* pedited) lastHaloControl = pp->sharpening.halocontrol; contrast->setValue (pp->sharpening.contrast); + blur->setValue (pp->sharpening.blurradius); amount->setValue (pp->sharpening.amount); radius->setValue (pp->sharpening.radius); threshold->setValue(pp->sharpening.threshold); @@ -224,6 +231,7 @@ void Sharpening::write (ProcParams* pp, ParamsEdited* pedited) { pp->sharpening.contrast = contrast->getValue (); + pp->sharpening.blurradius = blur->getValue (); pp->sharpening.amount = (int)amount->getValue(); pp->sharpening.enabled = getEnabled (); pp->sharpening.radius = radius->getValue (); @@ -246,6 +254,7 @@ void Sharpening::write (ProcParams* pp, ParamsEdited* pedited) if (pedited) { pedited->sharpening.contrast = contrast->getEditedState (); + pedited->sharpening.blurradius = blur->getEditedState (); pedited->sharpening.amount = amount->getEditedState (); pedited->sharpening.radius = radius->getEditedState (); pedited->sharpening.threshold = threshold->getEditedState (); @@ -266,6 +275,7 @@ void Sharpening::write (ProcParams* pp, ParamsEdited* pedited) void Sharpening::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) { contrast->setDefault (defParams->sharpening.contrast); + blur->setDefault (defParams->sharpening.blurradius); amount->setDefault (defParams->sharpening.amount); radius->setDefault (defParams->sharpening.radius); threshold->setDefault (defParams->sharpening.threshold); @@ -279,6 +289,7 @@ void Sharpening::setDefaults (const ProcParams* defParams, const ParamsEdited* p if (pedited) { contrast->setDefaultEditedState (pedited->sharpening.contrast ? Edited : UnEdited); + blur->setDefaultEditedState (pedited->sharpening.blurradius ? Edited : UnEdited); amount->setDefaultEditedState (pedited->sharpening.amount ? Edited : UnEdited); radius->setDefaultEditedState (pedited->sharpening.radius ? Edited : UnEdited); threshold->setDefaultEditedState (pedited->sharpening.threshold ? Edited : UnEdited); @@ -291,6 +302,7 @@ void Sharpening::setDefaults (const ProcParams* defParams, const ParamsEdited* p ddamping->setDefaultEditedState (pedited->sharpening.deconvdamping ? Edited : UnEdited); } else { contrast->setDefaultEditedState (Irrelevant); + blur->setDefaultEditedState (Irrelevant); amount->setDefaultEditedState (Irrelevant); radius->setDefaultEditedState (Irrelevant); threshold->setDefaultEditedState (Irrelevant); @@ -310,7 +322,7 @@ void Sharpening::adjusterChanged(Adjuster* a, double newval) Glib::ustring costr; - if (a == radius || a == dradius) { + if (a == radius || a == dradius || a == blur) { costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), a->getValue()); } else if (a == eradius) { costr = Glib::ustring::format (std::setw(2), std::fixed, std::setprecision(1), a->getValue()); @@ -324,6 +336,8 @@ void Sharpening::adjusterChanged(Adjuster* a, double newval) listener->panelChanged (EvShrAmount, costr); } else if (a == radius) { listener->panelChanged (EvShrRadius, costr); + } else if (a == blur) { + listener->panelChanged (EvSharpenBlur, costr); } else if (a == eradius) { listener->panelChanged (EvShrEdgeRadius, costr); } else if (a == etolerance) { @@ -487,6 +501,7 @@ void Sharpening::setBatchMode (bool batchMode) pack_start (*rld); contrast->showEditedCB (); + blur->showEditedCB (); radius->showEditedCB (); amount->showEditedCB (); threshold->showEditedCB (); @@ -518,6 +533,7 @@ void Sharpening::setAdjusterBehavior (bool contrastadd, bool radiusadd, bool amo void Sharpening::trimValues (rtengine::procparams::ProcParams* pp) { contrast->trimValue(pp->sharpening.contrast); + blur->trimValue(pp->sharpening.blurradius); radius->trimValue(pp->sharpening.radius); dradius->trimValue(pp->sharpening.deconvradius); amount->trimValue(pp->sharpening.amount); diff --git a/rtgui/sharpening.h b/rtgui/sharpening.h index fa5c956da..75ea083c9 100644 --- a/rtgui/sharpening.h +++ b/rtgui/sharpening.h @@ -29,6 +29,7 @@ class Sharpening : public ToolParamBlock, public ThresholdAdjusterListener, publ protected: Adjuster* contrast; + Adjuster* blur; MyComboBoxText* method; Adjuster* dradius; Adjuster* damount; @@ -55,6 +56,7 @@ protected: sigc::connection hcConn; rtengine::ProcEvent EvSharpenContrast; + rtengine::ProcEvent EvSharpenBlur; public: Sharpening (); From 7d17b2ef277c68c1eba9629af1ee518ba5fed2d6 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 8 Dec 2018 22:01:37 +0100 Subject: [PATCH 02/11] bugfix for last commit --- rtengine/ipsharpen.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 002337b2f..e72c665d5 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -242,7 +242,7 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); float contrast = sharpenParam.contrast / 100.f; - buildBlendMask(lab->L, blend, W, H, contrast, sharpenParam.method == "rld" ? 1.f : 1.f); + buildBlendMask(lab->L, blend, W, H, contrast, sharpenParam.method == "rld" ? sharpenParam.deconvamount / 100.f : 1.f); #ifdef _OPENMP #pragma omp parallel for #endif From 8bdec7c2de0fcb8757b19a534eadff9755d5d837 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 10 Dec 2018 14:29:23 +0100 Subject: [PATCH 03/11] Change blend between sharpened, original and blurred, #5075 --- rtengine/ipsharpen.cc | 64 +++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index e72c665d5..d722ddfdf 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -180,11 +180,21 @@ BENCHFUN buildBlendMask(luminance, blend, W, H, contrast, sharpenParam.deconvamount / 100.f); JaggedArray blur(W, H); - if(sharpenParam.blurradius > 0) { - #pragma omp parallel - { - gaussianBlur(tmpI, blur, W, H, sharpenParam.blurradius); - } + if (sharpenParam.blurradius >= 0.25f) { +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(tmpI, blur, W, H, sharpenParam.blurradius); +#ifdef _OPENMP + #pragma omp for +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + blur[i][j] = intp(blend[i][j], luminance[i][j], std::max(blur[i][j], 0.0f)); + } + } + } } const float damping = sharpenParam.deconvdamping / 5.0; const bool needdamp = sharpenParam.deconvdamping > 0; @@ -216,7 +226,7 @@ BENCHFUN } } - if(sharpenParam.blurradius > 0) { + if (sharpenParam.blurradius >= 0.25f) { #ifdef _OPENMP #pragma omp for #endif @@ -274,20 +284,31 @@ BENCHFUN } } - JaggedArray blur(W, H); - - if(sharpenParam.blurradius > 0) { - #pragma omp parallel - { - gaussianBlur(lab->L, blur, W, H, sharpenParam.blurradius); - } - } - // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); float contrast = sharpenParam.contrast / 100.f; buildBlendMask(lab->L, blend, W, H, contrast); + JaggedArray blur(W, H); + + if (sharpenParam.blurradius >= 0.25f) { +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(lab->L, blur, W, H, sharpenParam.blurradius); +#ifdef _OPENMP + #pragma omp for +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + blur[i][j] = intp(blend[i][j], lab->L[i][j], std::max(blur[i][j], 0.0f)); + } + } + } + } + + #ifdef _OPENMP #pragma omp parallel #endif @@ -349,16 +370,17 @@ BENCHFUN delete [] b3; } - if(sharpenParam.blurradius > 0) { + + if (sharpenParam.blurradius >= 0.25f) { #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for #endif - for (int i = 0; i < H; ++i) { - for (int j = 0; j < W; ++j) { - lab->L[i][j] = intp(blend[i][j], lab->L[i][j], max(blur[i][j], 0.0f)); - } + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + lab->L[i][j] = intp(blend[i][j], lab->L[i][j], max(blur[i][j], 0.0f)); } } + } } From 58e332475fcf131842a91816a340ee46cfcb148a Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 17 Dec 2018 13:07:46 +0100 Subject: [PATCH 04/11] Don't allocate blurbuffer when blur is disabled, #5075 --- rtengine/ipsharpen.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index d722ddfdf..1d699bb87 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -178,9 +178,11 @@ BENCHFUN JaggedArray blend(W, H); float contrast = sharpenParam.contrast / 100.f; buildBlendMask(luminance, blend, W, H, contrast, sharpenParam.deconvamount / 100.f); - JaggedArray blur(W, H); + JaggedArray* blurbuffer = nullptr; if (sharpenParam.blurradius >= 0.25f) { + blurbuffer = new JaggedArray(W, H); + JaggedArray &blur = *blurbuffer; #ifdef _OPENMP #pragma omp parallel #endif @@ -227,6 +229,7 @@ BENCHFUN } if (sharpenParam.blurradius >= 0.25f) { + JaggedArray &blur = *blurbuffer; #ifdef _OPENMP #pragma omp for #endif @@ -237,6 +240,7 @@ BENCHFUN } } } // end parallel + delete blurbuffer; } void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpenParam, bool showMask) From 988d598d9dcd0466054f7b04674dec77df6100b5 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 17 Dec 2018 13:26:14 +0100 Subject: [PATCH 05/11] Decouple sharpening amount from contrast mask, #5075 --- rtengine/ipsharpen.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 1d699bb87..8437fae47 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -159,7 +159,7 @@ extern const Settings* settings; void ImProcFunctions::deconvsharpening (float** luminance, float** tmp, int W, int H, const SharpeningParams &sharpenParam) { - if (sharpenParam.deconvamount == 0) { + if (sharpenParam.deconvamount == 0 && sharpenParam.blurradius < 0.25f) { return; } BENCHFUN @@ -177,7 +177,7 @@ BENCHFUN // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); float contrast = sharpenParam.contrast / 100.f; - buildBlendMask(luminance, blend, W, H, contrast, sharpenParam.deconvamount / 100.f); + buildBlendMask(luminance, blend, W, H, contrast, 1.f); JaggedArray* blurbuffer = nullptr; if (sharpenParam.blurradius >= 0.25f) { @@ -201,6 +201,7 @@ BENCHFUN const float damping = sharpenParam.deconvdamping / 5.0; const bool needdamp = sharpenParam.deconvdamping > 0; const double sigma = sharpenParam.deconvradius / scale; + const float amount = sharpenParam.deconvamount / 100.f; #ifdef _OPENMP #pragma omp parallel @@ -224,7 +225,7 @@ BENCHFUN for (int i = 0; i < H; ++i) { for (int j = 0; j < W; ++j) { - luminance[i][j] = intp(blend[i][j], max(tmpI[i][j], 0.0f), luminance[i][j]); + luminance[i][j] = intp(blend[i][j] * amount, max(tmpI[i][j], 0.0f), luminance[i][j]); } } @@ -256,7 +257,7 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); float contrast = sharpenParam.contrast / 100.f; - buildBlendMask(lab->L, blend, W, H, contrast, sharpenParam.method == "rld" ? sharpenParam.deconvamount / 100.f : 1.f); + buildBlendMask(lab->L, blend, W, H, contrast, 1.f); #ifdef _OPENMP #pragma omp parallel for #endif From 42beee886bbf4582b668e65817fe8aace3345488 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 26 Dec 2018 21:12:46 +0100 Subject: [PATCH 06/11] Preview sometimes goes magenta at >=100% preview when using Ciecam02 and defringe, fixes #5116 --- rtengine/PF_correct_RT.cc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/rtengine/PF_correct_RT.cc b/rtengine/PF_correct_RT.cc index dbb42db0d..57e4c2225 100644 --- a/rtengine/PF_correct_RT.cc +++ b/rtengine/PF_correct_RT.cc @@ -396,26 +396,26 @@ void ImProcFunctions::PF_correct_RTcam(CieImage * ncie, double radius, int thres } } } // end of ab channel averaging + } #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for #endif - for(int i = 0; i < height; i++) { - int j = 0; + for(int i = 0; i < height; i++) { + int j = 0; #ifdef __SSE2__ - for (; j < width - 3; j += 4) { - const vfloat interav = LVFU(tmaa[i][j]); - const vfloat interbv = LVFU(tmbb[i][j]); - STVFU(ncie->h_p[i][j], xatan2f(interbv, interav) / F2V(RT_PI_F_180)); - STVFU(ncie->C_p[i][j], vsqrtf(SQRV(interbv) + SQRV(interav))); - } + for (; j < width - 3; j += 4) { + const vfloat interav = LVFU(tmaa[i][j]); + const vfloat interbv = LVFU(tmbb[i][j]); + STVFU(ncie->h_p[i][j], xatan2f(interbv, interav) / F2V(RT_PI_F_180)); + STVFU(ncie->C_p[i][j], vsqrtf(SQRV(interbv) + SQRV(interav))); + } #endif - for (; j < width; j++) { - const float intera = tmaa[i][j]; - const float interb = tmbb[i][j]; - ncie->h_p[i][j] = xatan2f(interb, intera) / RT_PI_F_180; - ncie->C_p[i][j] = sqrt(SQR(interb) + SQR(intera)); - } + for (; j < width; j++) { + const float intera = tmaa[i][j]; + const float interb = tmbb[i][j]; + ncie->h_p[i][j] = xatan2f(interb, intera) / RT_PI_F_180; + ncie->C_p[i][j] = sqrt(SQR(interb) + SQR(intera)); } } } From e98d4e2f0753fa14b9b2975fdfe6384e5e03daed Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 27 Dec 2018 11:41:14 +0100 Subject: [PATCH 07/11] Dont open console window when -gimp is used, #5084 --- rtgui/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/main.cc b/rtgui/main.cc index 8996ee01d..b75fc0ec8 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -536,7 +536,7 @@ int main (int argc, char **argv) bool Console = true; for (int i = 1; i < argc; i++) - if (!strcmp (argv[i], "-w") || !strcmp (argv[i], "-R")) { + if (!strcmp (argv[i], "-w") || !strcmp (argv[i], "-R") || !strcmp (argv[i], "-gimp")) { Console = false; break; } From b9ec38054337f24619805c0e44f2126afc822ed0 Mon Sep 17 00:00:00 2001 From: Beep6581 Date: Fri, 28 Dec 2018 23:18:29 +0100 Subject: [PATCH 08/11] Added note on identifier naming Agreed to in IRC with Ingo and Hombre --- CONTRIBUTING.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7e79edc27..85776d557 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,11 +16,12 @@ The most useful feedback is based on the latest development code, and in the cas - Announce and discuss your plans in GitHub before starting work. - Work in a new branch. Fork if necessary. - Keep branches small so that completed and working features can be merged into the "dev" branch often, and so that they can be abandoned if they head in the wrong direction. -- Use C++11 +- Use C++11. - The naming isn't homogeneous throughout the code but here is a rough guideline: - - *Types* (classes, structs, enums, typedefs...) should be named with `UpperCamelCase` - - *Functions* and *methods* should be named with `lowerCamelCase` - - *Variables* should be either named with `lowerCamelCase` or better with `lower_underscores` to avoid conflicts - - *Enum values* should be named with `UPPER_UNDERSCORES` - - Most important: Be consistent, even when not sticking to the rules + - *Identifiers* (variables, functions, methods, keys, enums, etc.) should be clear and unambiguous. Make them as long as necessary to ensure that your code is understandable to others. + - *Types* (classes, structs, enums, typedefs...) should be named with `UpperCamelCase`. + - *Functions* and *methods* should be named with `lowerCamelCase`. + - *Variables* should be either named with `lowerCamelCase` or better with `lower_underscores` to avoid conflicts. + - *Enum values* should be named with `UPPER_UNDERSCORES`. + - Be consistent, even when not sticking to the rules. - Code may be run through astyle version 3 or newer. If using astyle, it is important that the astyle changes go into their own commit, so that style changes are not mixed with actual code changes. Command: `astyle --options=rawtherapee.astylerc code.cc` From 5a7f889380f9d3a8f16df796e4a95ee54a44882f Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 31 Dec 2018 16:15:50 +0100 Subject: [PATCH 09/11] Better xtrans fast algorithm, #5107 --- rtengine/xtrans_demosaic.cc | 63 +++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/rtengine/xtrans_demosaic.cc b/rtengine/xtrans_demosaic.cc index ed253749b..26cd9071b 100644 --- a/rtengine/xtrans_demosaic.cc +++ b/rtengine/xtrans_demosaic.cc @@ -960,59 +960,62 @@ void RawImageSource::xtrans_interpolate (const int passes, const bool useCieLab) #undef CLIP void RawImageSource::fast_xtrans_interpolate (const array2D &rawData, array2D &red, array2D &green, array2D &blue) { -// if (settings->verbose) { -// printf("fast X-Trans interpolation...\n"); -// } - double progress = 0.0; - const bool plistenerActive = plistener; - - if (plistenerActive) { - plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "fast Xtrans")); - plistener->setProgress (progress); + if (plistener) { + plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "fast Xtrans")); + plistener->setProgress(0.0); } - const int height = H, width = W; - - xtransborder_interpolate (1, red, green, blue); + xtransborder_interpolate(1, red, green, blue); int xtrans[6][6]; ri->getXtransMatrix(xtrans); - #pragma omp parallel for + const float weight[3][3] = { + {0.25f, 0.5f, 0.25f}, + {0.5f, 0.f, 0.5f}, + {0.25f, 0.5f, 0.25f} + }; +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) +#endif + for (int row = 1; row < H - 1; ++row) { + for (int col = 1; col < W - 1; ++col) { + float sum[3] = {}; - for(int row = 1; row < height - 1; row++) { - for(int col = 1; col < width - 1; col++) { - float sum[3] = {0.f}; - - for(int v = -1; v <= 1; v++) { - for(int h = -1; h <= 1; h++) { - sum[fcol(row + v, col + h)] += rawData[row + v][(col + h)]; + for (int v = -1; v <= 1; v++) { + for (int h = -1; h <= 1; h++) { + sum[fcol(row + v, col + h)] += rawData[row + v][(col + h)] * weight[v + 1][h + 1]; } } switch(fcol(row, col)) { - case 0: + case 0: // red pixel red[row][col] = rawData[row][col]; - green[row][col] = sum[1] * 0.2f; - blue[row][col] = sum[2] * 0.33333333f; + green[row][col] = sum[1] * 0.5f; + blue[row][col] = sum[2]; break; - case 1: - red[row][col] = sum[0] * 0.5f; + case 1: // green pixel green[row][col] = rawData[row][col]; - blue[row][col] = sum[2] * 0.5f; + if (fcol(row, col - 1) == fcol(row, col + 1)) { // Solitary green pixel always has exactly two direct red and blue neighbors in 3x3 grid + red[row][col] = sum[0]; + blue[row][col] = sum[2]; + } else { // Non solitary green pixel always has one direct and one diagonal red and blue neighbor in 3x3 grid + red[row][col] = sum[0] * 1.3333333f; + blue[row][col] = sum[2] * 1.3333333f; + } break; - case 2: - red[row][col] = sum[0] * 0.33333333f; - green[row][col] = sum[1] * 0.2f; + case 2: // blue pixel + red[row][col] = sum[0]; + green[row][col] = sum[1] * 0.5f; blue[row][col] = rawData[row][col]; break; } } } - if (plistenerActive) { + if (plistener) { plistener->setProgress (1.0); } } From 8e3e4afcaf9f1dd4a9ace5deeaaef90d8f1efbb6 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Mon, 31 Dec 2018 16:40:31 +0100 Subject: [PATCH 10/11] Select+focus thumbnail in Filmstrip, closes #5125 When passing a photo as an argument to the RawTherapee executable, the user wants this auto-loaded photo's thumbnail to be selected and visible in the Filmstrip. --- rtgui/editorpanel.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index f44e682f2..fc19f7f27 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1083,6 +1083,10 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) history->resetSnapShotNumber(); navigator->setInvalid(ipc->getFullWidth(),ipc->getFullHeight()); + + // When passing a photo as an argument to the RawTherapee executable, the user wants + // this auto-loaded photo's thumbnail to be selected and visible in the Filmstrip. + EditorPanel::syncFileBrowser(); } void EditorPanel::close () From d43ccc5e816f847ec153db612a94e061a24f05fe Mon Sep 17 00:00:00 2001 From: heckflosse Date: Mon, 31 Dec 2018 18:47:08 +0100 Subject: [PATCH 11/11] Add vceilf(x) --- rtengine/sleefsseavx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rtengine/sleefsseavx.c b/rtengine/sleefsseavx.c index 83d937bd1..3000c1c10 100644 --- a/rtengine/sleefsseavx.c +++ b/rtengine/sleefsseavx.c @@ -1427,5 +1427,21 @@ static INLINE void vconvertrgbrgbrgbrgb2rrrrggggbbbb (const float * src, vfloat bv = _mm_setr_ps(src[2],src[5],src[8],src[11]); } +#if defined( __SSE4_1__ ) && defined( __x86_64__ ) +static INLINE vfloat vceilf(vfloat x) { + return _mm_round_ps(x, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC); +} + +#else + +static INLINE vfloat vceilf(vfloat x) { + __m128i zerov = _mm_setzero_si128(); + zerov = _mm_cmpeq_epi32(zerov, zerov); + const vfloat onev = (vfloat)_mm_slli_epi32(_mm_srli_epi32(zerov, 25), 23); //create vector 1.0f + const vfloat xi = _mm_cvtepi32_ps(_mm_cvttps_epi32(x)); + return xi + _mm_and_ps(_mm_cmplt_ps(xi, x), onev); +} +#endif + #endif // __SSE2__ #endif // SLEEFSSEAVX