diff --git a/rtdata/languages/default b/rtdata/languages/default index ba96a43cb..d891d8692 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -765,6 +765,7 @@ HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius HISTORY_MSG_METADATA_MODE;Metadata copy mode HISTORY_MSG_MICROCONTRAST_CONTRAST;Microcontrast - Contrast threshold HISTORY_MSG_PDSHARPEN_CONTRAST;CAS - Contrast threshold +HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;CAS - Auto threshold HISTORY_MSG_PDSHARPEN_GAMMA;CAS - Gamma HISTORY_MSG_PDSHARPEN_ITERATIONS;CAS - Iterations HISTORY_MSG_PDSHARPEN_RADIUS;CAS - Radius diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 006fe59a6..46cbc28a6 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -182,7 +182,7 @@ public: return this; } virtual void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) = 0; - virtual void captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask) = 0; + virtual void captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold) = 0; }; } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 29d56e79e..7d485fd19 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -121,6 +121,7 @@ ImProcCoordinator::ImProcCoordinator() : flatFieldAutoClipListener(nullptr), bayerAutoContrastListener(nullptr), xtransAutoContrastListener(nullptr), + pdSharpenAutoContrastListener(nullptr), frameCountListener(nullptr), imageTypeListener(nullptr), actListener(nullptr), @@ -333,16 +334,21 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) double contrastThreshold = imgsrc->getSensorType() == ST_BAYER ? params->raw.bayersensor.dualDemosaicContrast : params->raw.xtranssensor.dualDemosaicContrast; imgsrc->demosaic(rp, autoContrast, contrastThreshold); //enabled demosaic - if (params->pdsharpening.enabled) { - imgsrc->captureSharpening(params->pdsharpening, sharpMask); - } if (imgsrc->getSensorType() == ST_BAYER && bayerAutoContrastListener && autoContrast) { - bayerAutoContrastListener->autoContrastChanged(autoContrast ? contrastThreshold : -1.0); - } - if (imgsrc->getSensorType() == ST_FUJI_XTRANS && xtransAutoContrastListener && autoContrast) { + bayerAutoContrastListener->autoContrastChanged(contrastThreshold); + } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS && xtransAutoContrastListener && autoContrast) { xtransAutoContrastListener->autoContrastChanged(autoContrast ? contrastThreshold : -1.0); } + if (params->pdsharpening.enabled) { + double pdSharpencontrastThreshold = params->pdsharpening.contrast; + imgsrc->captureSharpening(params->pdsharpening, sharpMask, pdSharpencontrastThreshold); + if (pdSharpenAutoContrastListener && params->pdsharpening.autoContrast) { + pdSharpenAutoContrastListener->autoContrastChanged(pdSharpencontrastThreshold); + } + } + + // if a demosaic happened we should also call getimage later, so we need to set the M_INIT flag todo |= M_INIT; diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 0315bc180..ef1c52bc6 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -161,6 +161,7 @@ protected: FlatFieldAutoClipListener *flatFieldAutoClipListener; AutoContrastListener *bayerAutoContrastListener; AutoContrastListener *xtransAutoContrastListener; + AutoContrastListener *pdSharpenAutoContrastListener; FrameCountListener *frameCountListener; ImageTypeListener *imageTypeListener; @@ -363,6 +364,11 @@ public: xtransAutoContrastListener = acl; } + void setpdSharpenAutoContrastListener (AutoContrastListener* acl) override + { + pdSharpenAutoContrastListener = acl; + } + void setImageTypeListener (ImageTypeListener* itl) override { imageTypeListener = itl; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index e1e66d99c..467f1446a 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), + autoContrast(false), blurradius(0.2), gamma(1.0), radius(0.5), @@ -1107,6 +1108,7 @@ bool SharpeningParams::operator ==(const SharpeningParams& other) const && radius == other.radius && amount == other.amount && threshold == other.threshold + && autoContrast == other.autoContrast && edgesonly == other.edgesonly && edges_radius == other.edges_radius && edges_tolerance == other.edges_tolerance @@ -2791,6 +2793,7 @@ void ProcParams::setDefaults() pdsharpening = {}; pdsharpening.contrast = 10.0; + pdsharpening.autoContrast = true; prsharpening.method = "rld"; pdsharpening.gamma = 1.35; pdsharpening.deconvradius = 0.75; @@ -3308,6 +3311,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // Post demosaic sharpening saveToKeyfile(!pedited || pedited->pdsharpening.enabled, "PostDemosaicSharpening", "Enabled", pdsharpening.enabled, keyFile); saveToKeyfile(!pedited || pedited->pdsharpening.contrast, "PostDemosaicSharpening", "Contrast", pdsharpening.contrast, keyFile); + saveToKeyfile(!pedited || pedited->pdsharpening.autoContrast, "PostDemosaicSharpening", "AutoContrast", pdsharpening.autoContrast, keyFile); saveToKeyfile(!pedited || pedited->pdsharpening.gamma, "PostDemosaicSharpening", "DeconvGamma", pdsharpening.gamma, keyFile); saveToKeyfile(!pedited || pedited->pdsharpening.deconvradius, "PostDemosaicSharpening", "DeconvRadius", pdsharpening.deconvradius, keyFile); saveToKeyfile(!pedited || pedited->pdsharpening.deconviter, "PostDemosaicSharpening", "DeconvIterations", pdsharpening.deconviter, keyFile); @@ -4395,6 +4399,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("PostDemosaicSharpening")) { assignFromKeyfile(keyFile, "PostDemosaicSharpening", "Enabled", pedited, pdsharpening.enabled, pedited->pdsharpening.enabled); assignFromKeyfile(keyFile, "PostDemosaicSharpening", "Contrast", pedited, pdsharpening.contrast, pedited->pdsharpening.contrast); + assignFromKeyfile(keyFile, "PostDemosaicSharpening", "AutoContrast", pedited, pdsharpening.autoContrast, pedited->pdsharpening.autoContrast); assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvGamma", pedited, pdsharpening.gamma, pedited->pdsharpening.gamma); assignFromKeyfile(keyFile, "PostDemosaicSharpening", "DeconvRadius", pedited, pdsharpening.deconvradius, pedited->pdsharpening.deconvradius); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index f9255f815..83b6c3e44 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -493,6 +493,7 @@ struct ColorToningParams { struct SharpeningParams { bool enabled; double contrast; + bool autoContrast; double blurradius; double gamma; double radius; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 25beb6208..d84c0436a 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -4953,7 +4953,7 @@ void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int } } -void RawImageSource::captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask) { +void RawImageSource::captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold) { BENCHFUN const float xyz_rgb[3][3] = { // XYZ from RGB @@ -4962,7 +4962,7 @@ BENCHFUN { 0.019334, 0.119193, 0.950227 } }; - float contrast = sharpeningParams.contrast / 100.f; + float contrast = conrastThreshold / 100.f; if (showMask) { StopWatch Stop1("Show mask"); @@ -4975,8 +4975,8 @@ BENCHFUN Color::RGB2L(red[i], green[i], blue[i], L[i], xyz_rgb, W); } array2D& blend = red; // red will be overridden anyway => we can use its buffer to store the blend mask - buildBlendMask(L, blend, W, H, contrast, 1.f); - + buildBlendMask(L, blend, W, H, contrast, 1.f, sharpeningParams.autoContrast); + conrastThreshold = contrast * 100.f; #ifdef _OPENMP #pragma omp parallel for #endif @@ -5002,7 +5002,8 @@ BENCHFUN } // calculate contrast based blend factors to reduce sharpening in regions with low contrast JaggedArray blend(W, H); - buildBlendMask(L, blend, W, H, contrast, 1.f); + buildBlendMask(L, blend, W, H, contrast, 1.f, sharpeningParams.autoContrast); + conrastThreshold = contrast * 100.f; Stop1.stop(); array2D& tmp = L; // L is not used anymore now => we can use its buffer as the needed temporary buffer diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index a7aee0843..8cf6b08a9 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -305,7 +305,7 @@ protected: void hflip (Imagefloat* im); void vflip (Imagefloat* im); void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override; - void captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask) override; + void captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold) override; }; } diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index ca4cebe2e..86e9ade75 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -523,6 +523,7 @@ public: virtual void setFrameCountListener (FrameCountListener* l) = 0; virtual void setBayerAutoContrastListener (AutoContrastListener* l) = 0; virtual void setXtransAutoContrastListener (AutoContrastListener* l) = 0; + virtual void setpdSharpenAutoContrastListener (AutoContrastListener* l) = 0; virtual void setAutoBWListener (AutoBWListener* l) = 0; virtual void setAutoWBListener (AutoWBListener* l) = 0; virtual void setAutoColorTonListener (AutoColorTonListener* l) = 0; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 24a3f3263..0524734e0 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -222,7 +222,7 @@ private: imgsrc->demosaic (params.raw, autoContrast, contrastThreshold); if (params.pdsharpening.enabled) { - imgsrc->captureSharpening(params.pdsharpening, false); + imgsrc->captureSharpening(params.pdsharpening, false, params.pdsharpening.contrast); } diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 5acb8d113..175f664f8 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -102,7 +102,7 @@ public: void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override { R = G = B = 0;} void flushRGB () override; - void captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask) override {}; + void captureSharpening(const procparams::SharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold) override {}; }; } #endif diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index da65cbf8e..4029d0b9b 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -167,6 +167,7 @@ void ParamsEdited::set(bool v) sharpening.deconvdamping = v; pdsharpening.enabled = v; pdsharpening.contrast = v; + pdsharpening.autoContrast = v; pdsharpening.gamma = v; pdsharpening.deconvamount = v; pdsharpening.deconvradius = v; @@ -751,6 +752,7 @@ void ParamsEdited::initFrom(const std::vector& sharpening.deconvdamping = sharpening.deconvdamping && p.sharpening.deconvdamping == other.sharpening.deconvdamping; pdsharpening.enabled = pdsharpening.enabled && p.pdsharpening.enabled == other.pdsharpening.enabled; pdsharpening.contrast = pdsharpening.contrast && p.pdsharpening.contrast == other.pdsharpening.contrast; + pdsharpening.autoContrast = pdsharpening.autoContrast && p.pdsharpening.autoContrast == other.pdsharpening.autoContrast; pdsharpening.gamma = pdsharpening.gamma && p.pdsharpening.gamma == other.pdsharpening.gamma; pdsharpening.deconvradius = pdsharpening.deconvradius && p.pdsharpening.deconvradius == other.pdsharpening.deconvradius; pdsharpening.deconviter = pdsharpening.deconviter && p.pdsharpening.deconviter == other.pdsharpening.deconviter; @@ -1727,6 +1729,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.pdsharpening.contrast = dontforceSet && options.baBehav[ADDSET_SHARP_CONTRAST] ? toEdit.pdsharpening.contrast + mods.pdsharpening.contrast : mods.pdsharpening.contrast; } + if (pdsharpening.autoContrast) { + toEdit.pdsharpening.autoContrast = mods.pdsharpening.autoContrast; + } + if (pdsharpening.deconvamount) { toEdit.pdsharpening.deconvamount = dontforceSet && options.baBehav[ADDSET_SHARP_AMOUNT] ? toEdit.pdsharpening.deconvamount + mods.pdsharpening.deconvamount : mods.pdsharpening.deconvamount; } @@ -3288,5 +3294,5 @@ bool FilmNegativeParamsEdited::isUnchanged() const bool SharpeningParamsEdited::isUnchanged() const { - return enabled && contrast && gamma && deconvradius && deconviter; + return enabled && contrast && autoContrast && gamma && deconvradius && deconviter; } \ No newline at end of file diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 5191bce56..6d229e689 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -179,6 +179,7 @@ struct SharpenMicroParamsEdited { struct SharpeningParamsEdited { bool enabled; bool contrast; + bool autoContrast; bool blurradius; bool gamma; bool radius; diff --git a/rtgui/pdsharpening.cc b/rtgui/pdsharpening.cc index 896d416b5..43b32ce7e 100644 --- a/rtgui/pdsharpening.cc +++ b/rtgui/pdsharpening.cc @@ -20,6 +20,7 @@ #include "eventmapper.h" #include "pdsharpening.h" #include "options.h" +#include "../rtengine/procparams.h" using namespace rtengine; using namespace rtengine::procparams; @@ -32,11 +33,15 @@ PdSharpening::PdSharpening () : FoldableToolPanel(this, "pdsharpening", M("TP_PD EvPdSharpenGamma = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_GAMMA"); EvPdShrDRadius = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_RADIUS"); EvPdShrDIterations = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_ITERATIONS"); + EvPdShrAutoContrast = m->newEvent(DEMOSAIC, "HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST"); Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); hb->show (); contrast = Gtk::manage(new Adjuster (M("TP_SHARPENING_CONTRAST"), 0, 200, 1, 10)); contrast->setAdjusterListener (this); + contrast->addAutoButton(M("TP_RAW_DUALDEMOSAICAUTOCONTRAST_TOOLTIP")); + contrast->setAutoValue(true); + pack_start(*contrast); contrast->show(); @@ -77,7 +82,7 @@ PdSharpening::PdSharpening () : FoldableToolPanel(this, "pdsharpening", M("TP_PD PdSharpening::~PdSharpening () { - + idle_register.destroy(); delete rld; } @@ -89,6 +94,7 @@ void PdSharpening::read (const ProcParams* pp, const ParamsEdited* pedited) if (pedited) { contrast->setEditedState (pedited->pdsharpening.contrast ? Edited : UnEdited); + contrast->setAutoInconsistent (multiImage && !pedited->pdsharpening.autoContrast); gamma->setEditedState (pedited->pdsharpening.gamma ? Edited : UnEdited); dradius->setEditedState (pedited->pdsharpening.deconvradius ? Edited : UnEdited); diter->setEditedState (pedited->pdsharpening.deconviter ? Edited : UnEdited); @@ -99,9 +105,11 @@ void PdSharpening::read (const ProcParams* pp, const ParamsEdited* pedited) setEnabled(pp->pdsharpening.enabled); contrast->setValue (pp->pdsharpening.contrast); + contrast->setAutoValue (pp->pdsharpening.autoContrast); gamma->setValue (pp->pdsharpening.gamma); dradius->setValue (pp->pdsharpening.deconvradius); diter->setValue (pp->pdsharpening.deconviter); + lastAutoContrast = pp->pdsharpening.autoContrast; enableListener (); } @@ -110,6 +118,7 @@ void PdSharpening::write (ProcParams* pp, ParamsEdited* pedited) { pp->pdsharpening.contrast = contrast->getValue (); + pp->pdsharpening.autoContrast = contrast->getAutoValue(); pp->pdsharpening.enabled = getEnabled (); pp->pdsharpening.gamma = gamma->getValue (); pp->pdsharpening.deconvradius = dradius->getValue (); @@ -117,6 +126,7 @@ void PdSharpening::write (ProcParams* pp, ParamsEdited* pedited) if (pedited) { pedited->pdsharpening.contrast = contrast->getEditedState (); + pedited->pdsharpening.autoContrast = !contrast->getAutoInconsistent (); pedited->pdsharpening.gamma = gamma->getEditedState (); pedited->pdsharpening.deconvradius = dradius->getEditedState (); pedited->pdsharpening.deconviter = diter->getEditedState (); @@ -182,26 +192,6 @@ void PdSharpening::enabledChanged () } } -void PdSharpening::adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) -{ -} - -void PdSharpening::adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) -{ -} - -void PdSharpening::adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop) -{ -} - -void PdSharpening::adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) -{ -} - -void PdSharpening::adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) -{ -} - void PdSharpening::setBatchMode (bool batchMode) { @@ -232,3 +222,43 @@ void PdSharpening::trimValues (rtengine::procparams::ProcParams* pp) dradius->trimValue(pp->pdsharpening.deconvradius); diter->trimValue(pp->pdsharpening.deconviter); } + +void PdSharpening::autoContrastChanged (double autoContrast) +{ + idle_register.add( + [this, autoContrast]() -> bool + { + disableListener(); + contrast->setValue(autoContrast); + enableListener(); + return false; + } + ); +} + +void PdSharpening::adjusterAutoToggled(Adjuster* a, bool newval) +{ + if (multiImage) { + if (contrast->getAutoInconsistent()) { + contrast->setAutoInconsistent (false); + contrast->setAutoValue (false); + } else if (lastAutoContrast) { + contrast->setAutoInconsistent (true); + } + + lastAutoContrast = contrast->getAutoValue(); + } + + if (listener) { + + if (a == contrast) { + if (contrast->getAutoInconsistent()) { + listener->panelChanged (EvPdShrAutoContrast, M ("GENERAL_UNCHANGED")); + } else if (contrast->getAutoValue()) { + listener->panelChanged (EvPdShrAutoContrast, M ("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvPdShrAutoContrast, M ("GENERAL_DISABLED")); + } + } + } +} diff --git a/rtgui/pdsharpening.h b/rtgui/pdsharpening.h index fe9359349..af09a9b6b 100644 --- a/rtgui/pdsharpening.h +++ b/rtgui/pdsharpening.h @@ -20,10 +20,9 @@ #include #include "adjuster.h" -#include "thresholdadjuster.h" #include "toolpanel.h" -class PdSharpening : public ToolParamBlock, public ThresholdAdjusterListener, public AdjusterListener, public FoldableToolPanel +class PdSharpening : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoContrastListener { protected: @@ -32,11 +31,14 @@ protected: Adjuster* dradius; Adjuster* diter; Gtk::VBox* rld; - + bool lastAutoContrast; rtengine::ProcEvent EvPdShrContrast; rtengine::ProcEvent EvPdShrDRadius; rtengine::ProcEvent EvPdSharpenGamma; rtengine::ProcEvent EvPdShrDIterations; + rtengine::ProcEvent EvPdShrAutoContrast; + IdleRegister idle_register; + public: PdSharpening (); @@ -47,14 +49,11 @@ public: void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void setBatchMode (bool batchMode) override; + void adjusterAutoToggled (Adjuster* a, bool newval) override; void adjusterChanged (Adjuster* a, double newval) override; void enabledChanged () override; - void adjusterChanged(ThresholdAdjuster* a, double newBottom, double newTop) override; - void adjusterChanged(ThresholdAdjuster* a, double newBottomLeft, double newTopLeft, double newBottomRight, double newTopRight) override; - void adjusterChanged(ThresholdAdjuster* a, int newBottom, int newTop) override; - void adjusterChanged(ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight) override; - void adjusterChanged2(ThresholdAdjuster* a, int newBottomL, int newTopL, int newBottomR, int newTopR) override; + void autoContrastChanged (double autoContrast) override; void setAdjusterBehavior (bool contrastadd, bool gammaadd, bool radiusadd, bool amountadd, bool dampingadd, bool iteradd, bool edgetoladd, bool haloctrladd); void trimValues (rtengine::procparams::ProcParams* pp) override; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 93f45aefe..f64205219 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -572,6 +572,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool ipc->setFlatFieldAutoClipListener (flatfield); ipc->setBayerAutoContrastListener (bayerprocess); ipc->setXtransAutoContrastListener (xtransprocess); + ipc->setpdSharpenAutoContrastListener (pdSharpening); ipc->setAutoWBListener (whitebalance); ipc->setAutoColorTonListener (colortoning); ipc->setAutoChromaListener (dirpyrdenoise);