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` diff --git a/rtdata/languages/default b/rtdata/languages/default index 2cb8c239f..ff55fb616 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -900,6 +900,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 @@ -2285,6 +2286,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/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)); } } } diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index e2e3c4cc6..a70f12c61 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 && sharpenParam.blurradius < 0.25f) { return; } BENCHFUN @@ -177,11 +177,31 @@ 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) { + blurbuffer = new JaggedArray(W, H); + JaggedArray &blur = *blurbuffer; +#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; const double sigma = sharpenParam.deconvradius / scale; + const float amount = sharpenParam.deconvamount / 100.f; #ifdef _OPENMP #pragma omp parallel @@ -205,10 +225,23 @@ 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]); + } + } + + if (sharpenParam.blurradius >= 0.25f) { + JaggedArray &blur = *blurbuffer; +#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 + delete blurbuffer; } 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) @@ -327,7 +360,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 @@ -364,6 +397,26 @@ BENCHFUN 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 @@ -425,6 +478,18 @@ BENCHFUN delete [] b3; } + + if (sharpenParam.blurradius >= 0.25f) { +#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 aff0ba8a1..f878deb4c 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 @@ -3303,6 +3305,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); @@ -4323,6 +4326,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 9c93ded7b..41fcef152 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -498,6 +498,7 @@ struct ColorToningParams { struct SharpeningParams { bool enabled; double contrast; + double blurradius; double radius; int amount; Threshold threshold; diff --git a/rtgui/main.cc b/rtgui/main.cc index c4deb12cb..1721867ba 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -537,7 +537,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; } diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index feef31784..179ffb8d3 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; @@ -850,6 +851,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; @@ -1901,6 +1903,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 8e94237e0..ca5c99ded 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 ();