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 ()