From 44729edf0417e4d652dbe19a9f94ffa0edb93b48 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 10 Jun 2018 14:35:12 +0200 Subject: [PATCH] Prepared engine to display the Sharpening Contrast mask --- rtdata/languages/default | 1 + rtengine/dcrop.cc | 4 ++-- rtengine/improccoordinator.cc | 7 +++++- rtengine/improccoordinator.h | 3 ++- rtengine/improcfun.cc | 5 +++-- rtengine/improcfun.h | 7 +++--- rtengine/ipsharpen.cc | 41 ++++++++++++++++++++++++++++++++--- rtengine/rtengine.h | 1 + rtgui/indclippedpanel.cc | 38 +++++++++++++++++++++++++++++--- rtgui/indclippedpanel.h | 7 ++++-- 10 files changed, 97 insertions(+), 17 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index d7653a230..590c59478 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -857,6 +857,7 @@ MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: < MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: > MAIN_TOOLTIP_PREVIEWB;Preview the Blue channel.\nShortcut: b MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the Focus Mask.\nShortcut: Shift-f\n\nMore accurate on images with shallow depth of field, low noise and at higher zoom levels.\n\nTo improve detection accuracy for noisy images evaluate at smaller zoom, about 10-30%. +MAIN_TOOLTIP_PREVIEWSHARPMASK;Preview the Sharpening Contrast Mask.\nShortcut: None\n\nOnly works when sharpening is enabled and zoom >= 100% MAIN_TOOLTIP_PREVIEWG;Preview the Green channel.\nShortcut: g MAIN_TOOLTIP_PREVIEWL;Preview the Luminosity.\nShortcut: v\n\n0.299*R + 0.587*G + 0.114*B MAIN_TOOLTIP_PREVIEWR;Preview the Red channel.\nShortcut: r diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index e2b4d2002..99aeccbe8 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -865,7 +865,7 @@ void Crop::update (int todo) if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { parent->ipf.MLmicrocontrast (labnCrop); - parent->ipf.sharpening (labnCrop, params.sharpening); + parent->ipf.sharpening (labnCrop, params.sharpening, parent->sharpMask); } } @@ -994,7 +994,7 @@ void Crop::update (int todo) float d, dj, yb; // not used after this block parent->ipf.ciecam_02float (cieCrop, float (adap), 1, 2, labnCrop, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, - dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, skip, execsharp, d, dj, yb, 1); + dummy, dummy, parent->CAMBrightCurveJ, parent->CAMBrightCurveQ, parent->CAMMean, 5, skip, execsharp, d, dj, yb, 1, parent->sharpMask); } else { // CIECAM is disabled, we free up its image buffer to save some space if (cieCrop) { diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index f39fe3415..714ad2b41 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -35,7 +35,7 @@ extern const Settings* settings; ImProcCoordinator::ImProcCoordinator () : orig_prev (nullptr), oprevi (nullptr), oprevl (nullptr), nprevl (nullptr), fattal_11_dcrop_cache(nullptr), previmg (nullptr), workimg (nullptr), ncie (nullptr), imgsrc (nullptr), lastAwbEqual (0.), lastAwbTempBias (0.0), ipf (¶ms, true), monitorIntent (RI_RELATIVE), - softProof (false), gamutCheck (false), scale (10), highDetailPreprocessComputed (false), highDetailRawComputed (false), + softProof (false), gamutCheck (false), sharpMask(false), scale (10), highDetailPreprocessComputed (false), highDetailRawComputed (false), allocated (false), bwAutoR (-9000.f), bwAutoG (-9000.f), bwAutoB (-9000.f), CAMMean (NAN), hltonecurve (65536), @@ -1160,6 +1160,11 @@ void ImProcCoordinator::getSoftProofing (bool &softProof, bool &gamutCheck) gamutCheck = this->gamutCheck; } +void ImProcCoordinator::setSharpMask (bool sharpMask) +{ + this->sharpMask = sharpMask; +} + void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb) { diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index ada7ed754..aabc9000b 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -76,6 +76,7 @@ protected: RenderingIntent monitorIntent; bool softProof; bool gamutCheck; + bool sharpMask; int scale; bool highDetailPreprocessComputed; @@ -271,7 +272,7 @@ public: void getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const; void setSoftProofing (bool softProof, bool gamutCheck); void getSoftProofing (bool &softProof, bool &gamutCheck); - + void setSharpMask (bool sharpMask); bool updateTryLock () { return updaterThreadStart.trylock(); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 5aea884fb..b5b4e1d13 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -462,7 +462,8 @@ void ImProcFunctions::firstAnalysis (const Imagefloat* const original, const Pro // Copyright (c) 2012 Jacques Desmis void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int pW, int pwb, LabImage* lab, const ProcParams* params, const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve2, const ColorAppearance & customColCurve3, - LUTu & histLCAM, LUTu & histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt) + LUTu & histLCAM, LUTu & histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt, + bool showSharpMask) { if (params->colorappearance.enabled) { @@ -1675,7 +1676,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int pW, int pw if (params->sharpening.enabled) if (execsharp) { float **buffer = lab->L; // We can use the L-buffer from lab as buffer to save some memory - ImProcFunctions::sharpeningcam (ncie, buffer); // sharpening adapted to CIECAM + ImProcFunctions::sharpeningcam (ncie, buffer, showSharpMask); // sharpening adapted to CIECAM } //if(params->dirpyrequalizer.enabled) if(execsharp) { diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 78f0c5b9e..003e09be2 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -222,12 +222,13 @@ public: void luminanceCurve (LabImage* lold, LabImage* lnew, LUTf &curve); void ciecam_02float (CieImage* ncie, float adap, int pW, int pwb, LabImage* lab, const ProcParams* params, const ColorAppearance & customColCurve1, const ColorAppearance & customColCurve, const ColorAppearance & customColCurve3, - LUTu &histLCAM, LUTu &histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt); + LUTu &histLCAM, LUTu &histCCAM, LUTf & CAMBrightCurveJ, LUTf & CAMBrightCurveQ, float &mean, int Iterates, int scale, bool execsharp, float &d, float &dj, float &yb, int rtt, + bool showSharpMask = false); void chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve, LUTf & satclcurve, LUTf &clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histLurve); void vibrance (LabImage* lab);//Jacques' vibrance // void colorCurve (LabImage* lold, LabImage* lnew); - void sharpening (LabImage* lab, const SharpeningParams &sharpenParam); - void sharpeningcam (CieImage* ncie, float** buffer); + void sharpening (LabImage* lab, const SharpeningParams &sharpenParam, bool showMask = false); + void sharpeningcam (CieImage* ncie, float** buffer, bool showMask = false); void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage); float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb (LabImage* lab, Image8* image); diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 855a8a8c9..6387cfde5 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -220,7 +220,7 @@ BENCHFUN } // end parallel } -void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpenParam) +void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpenParam, bool showMask) { if ((!sharpenParam.enabled) || sharpenParam.amount < 1 || lab->W < 8 || lab->H < 8) { @@ -228,6 +228,23 @@ void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpen } int W = lab->W, H = lab->H; + + if(showMask) { + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + JaggedArray blend(W, H); + buildBlendMask(lab->L, blend, W, H, sharpenParam.contrast / 100.f); +#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] = blend[i][j] * 32768.f; + } + } + return; + } + JaggedArray b2(W, H); if (sharpenParam.method == "rld") { @@ -801,12 +818,31 @@ void ImProcFunctions::MLmicrocontrastcam(CieImage* ncie) MLmicrocontrast(ncie->sh_p, ncie->W, ncie->H); } -void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2) +void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2, bool showMask) { if ((!params->sharpening.enabled) || params->sharpening.amount < 1 || ncie->W < 8 || ncie->H < 8) { return; } + int W = ncie->W, H = ncie->H; + + if(showMask) { + // calculate contrast based blend factors to reduce sharpening in regions with low contrast + JaggedArray blend(W, H); + buildBlendMask(ncie->sh_p, blend, W, H, params->sharpening.contrast / 100.f); +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + ncie->sh_p[i][j] = blend[i][j] * 32768.f; + } + } + return; + } + + if (params->sharpening.method == "rld") { deconvsharpening (ncie->sh_p, b2, ncie->W, ncie->H, params->sharpening); return; @@ -814,7 +850,6 @@ void ImProcFunctions::sharpeningcam (CieImage* ncie, float** b2) // Rest is UNSHARP MASK - int W = ncie->W, H = ncie->H; float** b3 = nullptr; if (params->sharpening.edgesonly) { diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index f50321775..c76c542e3 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -482,6 +482,7 @@ public: virtual void getMonitorProfile (Glib::ustring& monitorProfile, RenderingIntent& intent) const = 0; virtual void setSoftProofing (bool softProof, bool gamutCheck) = 0; virtual void getSoftProofing (bool &softProof, bool &gamutCheck) = 0; + virtual void setSharpMask (bool sharpMask) = 0; virtual ~StagedImageProcessor () {} diff --git a/rtgui/indclippedpanel.cc b/rtgui/indclippedpanel.cc index ae7cff644..35cfa843d 100644 --- a/rtgui/indclippedpanel.cc +++ b/rtgui/indclippedpanel.cc @@ -27,11 +27,20 @@ IndicateClippedPanel::IndicateClippedPanel (ImageArea* ia) : imageArea(ia) iFon = new RTImage ("previewmodeF-focusScreen-on.png"); iFoff = new RTImage ("previewmodeF-focusScreen-off.png"); + // for previewSharpMask, needs to be replaced with different icons + iSon = new RTImage ("previewmodeF-focusScreen-on.png"); + iSoff = new RTImage ("previewmodeF-focusScreen-off.png"); + previewFocusMask = Gtk::manage (new Gtk::ToggleButton ()); previewFocusMask->set_relief(Gtk::RELIEF_NONE); previewFocusMask->set_tooltip_markup (M("MAIN_TOOLTIP_PREVIEWFOCUSMASK")); previewFocusMask->set_image(*iFoff); + previewSharpMask = Gtk::manage (new Gtk::ToggleButton ()); + previewSharpMask->set_relief(Gtk::RELIEF_NONE); + previewSharpMask->set_tooltip_markup (M("MAIN_TOOLTIP_PREVIEWSHARPMASK")); + previewSharpMask->set_image(*iSoff); + Glib::ustring tt; indClippedH = Gtk::manage (new Gtk::ToggleButton ()); @@ -57,13 +66,16 @@ IndicateClippedPanel::IndicateClippedPanel (ImageArea* ia) : imageArea(ia) } previewFocusMask->set_active (false); + previewSharpMask->set_active (false); indClippedH->set_active (options.showClippedHighlights); indClippedS->set_active (options.showClippedShadows); pack_start (*previewFocusMask, Gtk::PACK_SHRINK, 0); + pack_start (*previewSharpMask, Gtk::PACK_SHRINK, 0); pack_start (*indClippedS, Gtk::PACK_SHRINK, 0); pack_start (*indClippedH, Gtk::PACK_SHRINK, 0); + connSharpMask = previewSharpMask->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled), previewSharpMask) ); connFocusMask = previewFocusMask->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled), previewFocusMask) ); connClippedS = indClippedS->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled), indClippedS) ); connClippedH = indClippedH->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled), indClippedH) ); @@ -86,27 +98,45 @@ void IndicateClippedPanel::toggleFocusMask () previewFocusMask->set_active(!previewFocusMask->get_active()); } +void IndicateClippedPanel::toggleSharpMask () +{ + previewSharpMask->set_active(!previewSharpMask->get_active()); +} + void IndicateClippedPanel::buttonToggled (Gtk::ToggleButton* tb) { connFocusMask.block(true); + connSharpMask.block(true); connClippedS.block(true); connClippedH.block(true); - if (tb != previewFocusMask) { - previewFocusMask->set_active(false); - } else { + if (tb == previewFocusMask) { if (indClippedS->get_active()) { indClippedS->set_active(false); } if (indClippedH->get_active()) { indClippedH->set_active(false); } + previewSharpMask->set_active(false); + } else if (tb == previewSharpMask) { + if (indClippedS->get_active()) { + indClippedS->set_active(false); + } + if (indClippedH->get_active()) { + indClippedH->set_active(false); + } + previewFocusMask->set_active(false); + } else { + previewFocusMask->set_active(false); + previewSharpMask->set_active(false); } previewFocusMask->set_image(previewFocusMask->get_active() ? *iFon : *iFoff); + previewSharpMask->set_image(previewSharpMask->get_active() ? *iSon : *iSoff); connFocusMask.block(false); + connSharpMask.block(false); connClippedS.block(false); connClippedH.block(false); @@ -123,4 +153,6 @@ IndicateClippedPanel::~IndicateClippedPanel () { delete iFon; delete iFoff; + delete iSon; + delete iSoff; } diff --git a/rtgui/indclippedpanel.h b/rtgui/indclippedpanel.h index 1da4b61de..b4225a9cb 100644 --- a/rtgui/indclippedpanel.h +++ b/rtgui/indclippedpanel.h @@ -19,13 +19,15 @@ #define _INDCLIPPEDPANEL_ #include +#include class ImageArea; class IndicateClippedPanel : public Gtk::HBox { protected: - Gtk::Image* iFon, *iFoff; + Gtk::Image* iFon, *iFoff, *iSon, *iSoff; + Gtk::ToggleButton* previewSharpMask; Gtk::ToggleButton* previewFocusMask; Gtk::ToggleButton* indClippedH; Gtk::ToggleButton* indClippedS; @@ -38,8 +40,9 @@ public: void buttonToggled(Gtk::ToggleButton* tb); void toggleClipped(bool highlights); // inverts a toggle programmatically void toggleFocusMask(); + void toggleSharpMask(); - sigc::connection connFocusMask, connClippedS, connClippedH; + sigc::connection connFocusMask, connSharpMask, connClippedS, connClippedH; bool showFocusMask ()