diff --git a/rtdata/languages/default b/rtdata/languages/default index a75272638..1c298f09a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -856,6 +856,7 @@ HISTORY_MSG_599;Local - Retinex dehaze HISTORY_MSG_600;Local - Soft Light enable HISTORY_MSG_601;Local - Soft Light strength HISTORY_MSG_602;Local - Soft Light scope +HISTORY_MSG_603;Local - Sh Blur radius HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction @@ -2011,6 +2012,7 @@ TP_LOCALLAB_SHARRADIUS;Radius TP_LOCALLAB_SHARAMOUNT;Amount TP_LOCALLAB_SHARDAMPING;Damping TP_LOCALLAB_SHARITER;Iterations +TP_LOCALLAB_SHARBLUR;Blur radius TP_LOCALLAB_SENSIS;Scope TP_LOCALLAB_SENSICB;Scope TP_LOCALLAB_SENSIBN;Scope diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 64dd6197a..58431d8a9 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -253,7 +253,7 @@ public: void Lanczos(const Imagefloat* src, Imagefloat* dst, float scale); void deconvsharpening(float** luminance, float** buffer, int W, int H, const SharpeningParams &sharpenParam); - void deconvsharpeningloc(float** luminance, float** buffer, int W, int H, float** loctemp, int damp, double radi, int ite, int amo, int contrast); + void deconvsharpeningloc(float** luminance, float** buffer, int W, int H, float** loctemp, int damp, double radi, int ite, int amo, int contrast, double blurrad); void MLsharpen(LabImage* lab); // Manuel's clarity / sharpening void MLmicrocontrast(float** luminance, int W, int H); //Manuel's microcontrast diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 8fc79a81f..2b165fb7a 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -161,6 +161,7 @@ struct local_params { float strng; float lcamount; double shrad; + double shblurr; double rad; double stren; int trans; @@ -439,6 +440,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall double radius = (double) locallab.radius.at(sp); double sharradius = ((double) locallab.sharradius.at(sp)) / 100. ; double lcamount = ((double) locallab.lcamount.at(sp)) / 100. ; + double sharblurr = ((double) locallab.sharblur.at(sp)) / 100. ; int local_sensisha = locallab.sensisha.at(sp); int local_sharamount = locallab.sharamount.at(sp); int local_shardamping = locallab.shardamping.at(sp); @@ -494,6 +496,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.invshar = inversesha; lp.str = str; lp.shrad = sharradius; + lp.shblurr = sharblurr; lp.senssha = local_sensisha; lp.shamo = local_sharamount; lp.shdamp = local_shardamping; @@ -12199,10 +12202,10 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu // } //sharpen only square area instaed of all image - ImProcFunctions::deconvsharpeningloc(bufsh, hbuffer, bfw, bfh, loctemp, params->locallab.shardamping.at(sp), (double)params->locallab.sharradius.at(sp) / 100., params->locallab.shariter.at(sp), params->locallab.sharamount.at(sp), params->locallab.sharcontrast.at(sp)); + ImProcFunctions::deconvsharpeningloc(bufsh, hbuffer, bfw, bfh, loctemp, params->locallab.shardamping.at(sp), (double)params->locallab.sharradius.at(sp) / 100., params->locallab.shariter.at(sp), params->locallab.sharamount.at(sp), params->locallab.sharcontrast.at(sp),(double)params->locallab.sharblur.at(sp) / 100.); } else { //call from dcrop.cc - ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, bfw, bfh, loctemp, params->locallab.shardamping.at(sp), (double)params->locallab.sharradius.at(sp) / 100., params->locallab.shariter.at(sp), params->locallab.sharamount.at(sp), params->locallab.sharcontrast.at(sp)); + ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, bfw, bfh, loctemp, params->locallab.shardamping.at(sp), (double)params->locallab.sharradius.at(sp) / 100., params->locallab.shariter.at(sp), params->locallab.sharamount.at(sp), params->locallab.sharcontrast.at(sp),(double)params->locallab.sharblur.at(sp) / 100.); } @@ -12225,7 +12228,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, LUTf & sobelrefs, float** shbu int GH = original->H; JaggedArray loctemp(GW, GH); - ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, GW, GH, loctemp, params->locallab.shardamping.at(sp), (double)params->locallab.sharradius.at(sp) / 100., params->locallab.shariter.at(sp), params->locallab.sharamount.at(sp), params->locallab.sharcontrast.at(sp)); + ImProcFunctions::deconvsharpeningloc(original->L, shbuffer, GW, GH, loctemp, params->locallab.shardamping.at(sp), (double)params->locallab.sharradius.at(sp) / 100., params->locallab.shariter.at(sp), params->locallab.sharamount.at(sp), params->locallab.sharcontrast.at(sp),(double)params->locallab.sharblur.at(sp) / 100.); float hueplus = hueref + dhuesha; float huemoins = hueref - dhuesha; diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 248d2c3be..e2e3c4cc6 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -211,7 +211,7 @@ BENCHFUN } // end parallel } -void ImProcFunctions::deconvsharpeningloc (float** luminance, float** tmp, int W, int H, float** loctemp, int damp, double radi, int ite, int amo, int contrast) +void ImProcFunctions::deconvsharpeningloc (float** luminance, float** tmp, int W, int H, float** loctemp, int damp, double radi, int ite, int amo, int contrast, double blurrad) { // BENCHFUN @@ -236,18 +236,36 @@ void ImProcFunctions::deconvsharpeningloc (float** luminance, float** tmp, int W // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); float contras = contrast / 100.f; - buildBlendMask(luminance, blend, W, H, contras, amo / 100.f); + buildBlendMask(luminance, blend, W, H, contras, 1.f); + JaggedArray blur(W, H); + + if (blurrad >= 0.25) { +#ifdef _OPENMP + #pragma omp parallel +#endif + { + gaussianBlur(tmpI, blur, W, H, blurrad); +#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)); + } + } + } + } float damping = (float) damp / 5.0; bool needdamp = damp > 0; double sigma = radi / scale; + const float amount = (float) amo / 100.f; if (sigma < 0.26f) { sigma = 0.26f; } int itera = ite; - // printf("OK 2 damp=%f sigam=%f iter=%i\n", damping, sigma, itera); #ifdef _OPENMP #pragma omp parallel @@ -266,8 +284,6 @@ void ImProcFunctions::deconvsharpeningloc (float** luminance, float** tmp, int W gaussianBlur (tmp, tmpI, W, H, sigma, nullptr, GAUSS_MULT); } // end for - // float p2 = (float) amo / 100.0; - // float p1 = 1.0 - p2; #ifdef _OPENMP #pragma omp for @@ -275,9 +291,20 @@ void ImProcFunctions::deconvsharpeningloc (float** luminance, float** tmp, int W for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) { - // loctemp[i][j] = luminance[i][j] * p1 + max (tmpI[i][j], 0.0f) * p2; - loctemp[i][j] = intp(blend[i][j], max(tmpI[i][j], 0.0f), luminance[i][j]); + loctemp[i][j] = intp(blend[i][j] * amount, max(tmpI[i][j], 0.0f), luminance[i][j]); } + + if (blurrad >= 0.25) { +#ifdef _OPENMP + #pragma omp for +#endif + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + loctemp[i][j] = intp(blend[i][j], loctemp[i][j], max(blur[i][j], 0.0f)); + } + } + } + } // end parallel delete [] tmpI[0]; diff --git a/rtengine/procevents.h b/rtengine/procevents.h index e41ac4418..7fb2a750f 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -629,6 +629,7 @@ enum ProcEventCode { EvLocenasoft = 599, Evlocallabstreng = 600, Evlocallabsensisf = 601, + Evlocallabsharblur = 602, NUMOFEVENTS }; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 9fa8317be..0e040fa41 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2426,6 +2426,7 @@ LocallabParams::LocallabParams() : sharamount(), shardamping(), shariter(), + sharblur(), sensisha(), inverssha(), //local contrast @@ -2555,6 +2556,7 @@ bool LocallabParams::operator ==(const LocallabParams& other) const && sharamount == other.sharamount && shardamping == other.shardamping && shariter == other.shariter + && sharblur == other.sharblur && sensisha == other.sensisha && inverssha == other.inverssha //local contrast @@ -3612,6 +3614,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->locallab.sharamount, "Locallab", "Sharamount_" + std::to_string(i), locallab.sharamount.at(i), keyFile); saveToKeyfile(!pedited || pedited->locallab.shardamping, "Locallab", "Shardamping_" + std::to_string(i), locallab.shardamping.at(i), keyFile); saveToKeyfile(!pedited || pedited->locallab.shariter, "Locallab", "Shariter_" + std::to_string(i), locallab.shariter.at(i), keyFile); + saveToKeyfile(!pedited || pedited->locallab.sharblur, "Locallab", "Sharblur_" + std::to_string(i), locallab.sharblur.at(i), keyFile); saveToKeyfile(!pedited || pedited->locallab.sensisha, "Locallab", "Sensisha_" + std::to_string(i), locallab.sensisha.at(i), keyFile); saveToKeyfile(!pedited || pedited->locallab.inverssha, "Locallab", "Inverssha_" + std::to_string(i), locallab.inverssha.at(i), keyFile); //local contrast @@ -4804,6 +4807,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) locallab.sharamount.resize(locallab.nbspot); locallab.shardamping.resize(locallab.nbspot); locallab.shariter.resize(locallab.nbspot); + locallab.sharblur.resize(locallab.nbspot); locallab.sensisha.resize(locallab.nbspot); locallab.inverssha.resize(locallab.nbspot); //local contrast @@ -4942,6 +4946,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "Sharamount_" + std::to_string(i), pedited, locallab.sharamount.at(i), pedited->locallab.sharamount); assignFromKeyfile(keyFile, "Locallab", "Shardamping_" + std::to_string(i), pedited, locallab.shardamping.at(i), pedited->locallab.shardamping); assignFromKeyfile(keyFile, "Locallab", "Shariter_" + std::to_string(i), pedited, locallab.shariter.at(i), pedited->locallab.shariter); + assignFromKeyfile(keyFile, "Locallab", "Sharblur_" + std::to_string(i), pedited, locallab.sharblur.at(i), pedited->locallab.sharblur); assignFromKeyfile(keyFile, "Locallab", "Sensisha_" + std::to_string(i), pedited, locallab.sensisha.at(i), pedited->locallab.sensisha); assignFromKeyfile(keyFile, "Locallab", "Inverssha_" + std::to_string(i), pedited, locallab.inverssha.at(i), pedited->locallab.inverssha); //local contrast diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 7c0644359..10529ef0a 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1015,6 +1015,7 @@ struct LocallabParams { std::vector shardamping; std::vector shariter; std::vector sensisha; + std::vector sharblur; std::vector inverssha; //local contrast std::vector expcontrast; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index c129c9dff..f6aa932f8 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -628,7 +628,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, //Evlocallabdehaz LUMINANCECURVE, //EvLocenasoft LUMINANCECURVE, //EvLocallabstreng - LUMINANCECURVE //EvLocallabsensisf + LUMINANCECURVE, //EvLocallabsensisf + LUMINANCECURVE //Evlocallabsharblur }; diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index ade3f1f42..1119cb227 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -108,6 +108,7 @@ Locallab::Locallab(): sensih(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SENSIH"), 0, 100, 1, 19))), // Sharpening sharcontrast(Gtk::manage(new Adjuster(M("TP_SHARPENING_CONTRAST"), 0, 200, 1, 20))), + sharblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARBLUR"), 20, 200, 1, 20))), sharradius(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHARRADIUS"), 42, 500, 1, 4))), 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, 75))), @@ -524,6 +525,8 @@ Locallab::Locallab(): shariter->setAdjusterListener(this); + sharblur->setAdjusterListener(this); + sensisha->set_tooltip_text(M("TP_LOCALLAB_SENSIS_TOOLTIP")); sensisha->setAdjusterListener(this); @@ -531,6 +534,7 @@ Locallab::Locallab(): ToolParamBlock* const sharpBox = Gtk::manage(new ToolParamBlock()); sharpBox->pack_start(*sharcontrast); + sharpBox->pack_start(*sharblur); sharpBox->pack_start(*sharradius); sharpBox->pack_start(*sharamount); sharpBox->pack_start(*shardamping); @@ -945,6 +949,7 @@ void Locallab::read(const ProcParams* pp, const ParamsEdited* pedited) shardamping->setEditedState(pedited->locallab.shardamping ? Edited : UnEdited); shariter->setEditedState(pedited->locallab.shariter ? Edited : UnEdited); sensisha->setEditedState(pedited->locallab.sensisha ? Edited : UnEdited); + sharblur->setEditedState(pedited->locallab.sharblur ? Edited : UnEdited); inverssha->set_inconsistent(multiImage && !pedited->locallab.inverssha); // local contrast @@ -1203,6 +1208,7 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pp->locallab.sharamount.push_back(100); pp->locallab.shardamping.push_back(75); pp->locallab.shariter.push_back(30); + pp->locallab.sharblur.push_back(20); pp->locallab.sensisha.push_back(19); pp->locallab.inverssha.push_back(0); //local contrast @@ -1347,6 +1353,7 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pp->locallab.sharamount.erase(pp->locallab.sharamount.begin() + i); pp->locallab.shardamping.erase(pp->locallab.shardamping.begin() + i); pp->locallab.shariter.erase(pp->locallab.shariter.begin() + i); + pp->locallab.sharblur.erase(pp->locallab.sharblur.begin() + i); pp->locallab.sensisha.erase(pp->locallab.sensisha.begin() + i); pp->locallab.inverssha.erase(pp->locallab.inverssha.begin() + i); //local contrast @@ -1568,6 +1575,7 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pp->locallab.sharamount.at(pp->locallab.selspot) = sharamount->getIntValue(); pp->locallab.shardamping.at(pp->locallab.selspot) = shardamping->getIntValue(); pp->locallab.shariter.at(pp->locallab.selspot) = shariter->getIntValue(); + pp->locallab.sharblur.at(pp->locallab.selspot) = sharblur->getIntValue(); pp->locallab.sensisha.at(pp->locallab.selspot) = sensisha->getIntValue(); pp->locallab.inverssha.at(pp->locallab.selspot) = (int)inverssha->get_active(); //local contrast @@ -1704,6 +1712,7 @@ void Locallab::write(ProcParams* pp, ParamsEdited* pedited) pedited->locallab.sharamount = sharamount->getEditedState(); pedited->locallab.shardamping = shardamping->getEditedState(); pedited->locallab.shariter = shariter->getEditedState(); + pedited->locallab.sharblur = sharblur->getEditedState(); pedited->locallab.sensisha = sensisha->getEditedState(); pedited->locallab.inverssha = !inverssha->get_inconsistent(); //local contrast @@ -2636,6 +2645,12 @@ void Locallab::adjusterChanged(Adjuster * a, double newval) } } + if (a == sharblur) { + if (listener) { + listener->panelChanged(Evlocallabsharblur, sharblur->getTextValue()); + } + } + if (a == sensisha) { if (listener) { listener->panelChanged(Evlocallabsensis, sensisha->getTextValue()); @@ -2917,6 +2932,7 @@ void Locallab::setBatchMode(bool batchMode) sharamount->showEditedCB(); shardamping->showEditedCB(); shariter->showEditedCB(); + sharblur->showEditedCB(); lcradius->showEditedCB(); lcamount->showEditedCB(); lcdarkness->showEditedCB(); @@ -3265,6 +3281,7 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, int sharamount->setValue(pp->locallab.sharamount.at(index)); shardamping->setValue(pp->locallab.shardamping.at(index)); shariter->setValue(pp->locallab.shariter.at(index)); + sharblur->setValue(pp->locallab.sharblur.at(index)); sensisha->setValue(pp->locallab.sensisha.at(index)); inverssha->set_active((bool)pp->locallab.inverssha.at(index)); diff --git a/rtgui/locallab.h b/rtgui/locallab.h index 3215b31b8..aad15a336 100644 --- a/rtgui/locallab.h +++ b/rtgui/locallab.h @@ -115,6 +115,7 @@ private: Adjuster* const sensih; // Sharpening Adjuster* const sharcontrast; + Adjuster* const sharblur; Adjuster* const sharradius; Adjuster* const sharamount; Adjuster* const shardamping; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 7ec1a7443..aa0c8b954 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -422,6 +422,7 @@ void ParamsEdited::set(bool v) locallab.sharamount = v; locallab.shardamping = v; locallab.shariter = v; + locallab.sharblur = v; locallab.sensisha = v; locallab.inverssha = v; //local contrast @@ -1118,6 +1119,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.sharamount = locallab.sharamount && p.locallab.sharamount == other.locallab.sharamount; locallab.shardamping = locallab.shardamping && p.locallab.shardamping == other.locallab.shardamping; locallab.shariter = locallab.shariter && p.locallab.shariter == other.locallab.shariter; + locallab.sharblur = locallab.sharblur && p.locallab.sharblur == other.locallab.sharblur; locallab.sensisha = locallab.sensisha && p.locallab.sensisha == other.locallab.sensisha; locallab.inverssha = locallab.inverssha && p.locallab.inverssha == other.locallab.inverssha; //local contrast @@ -2872,6 +2874,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.shariter = mods.locallab.shariter; } + if (locallab.sharblur) { + toEdit.locallab.sharblur = mods.locallab.sharblur; + } + if (locallab.sensisha) { toEdit.locallab.sensisha = mods.locallab.sensisha; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 061df5101..8031a7be3 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -552,6 +552,7 @@ public: bool sharamount; bool shardamping; bool shariter; + bool sharblur; bool sensisha; bool inverssha; //local contrast