diff --git a/rtdata/languages/default b/rtdata/languages/default
index c6c7d08ba..b1ded30f3 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -731,6 +731,7 @@ HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast
HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;Local Contrast - Lightness
HISTORY_MSG_LOCALCONTRAST_RADIUS;Local Contrast - Radius
HISTORY_MSG_METADATA_MODE;Metadata copy mode
+HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction
HISTORY_MSG_TM_FATTAL_ANCHOR;HDR TM - Anchor
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
@@ -1724,6 +1725,10 @@ TP_PREPROCESS_HOTPIXFILT;Hot pixel filter
TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels.
TP_PREPROCESS_LABEL;Preprocessing
TP_PREPROCESS_LINEDENOISE;Line noise filter
+TP_PREPROCESS_LINEDENOISE_DIRECTION;Direction
+TP_PREPROCESS_LINEDENOISE_DIRECTION_BOTH;Both
+TP_PREPROCESS_LINEDENOISE_DIRECTION_HORIZONTAL;Horizontal
+TP_PREPROCESS_LINEDENOISE_DIRECTION_VERTICAL;Vertical
TP_PREPROCESS_NO_FOUND;None found
TP_PRSHARPENING_LABEL;Post-Resize Sharpening
TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions.
diff --git a/rtengine/cfa_linedn_RT.cc b/rtengine/cfa_linedn_RT.cc
index 0f9e27634..67fb4b337 100644
--- a/rtengine/cfa_linedn_RT.cc
+++ b/rtengine/cfa_linedn_RT.cc
@@ -39,7 +39,7 @@ using namespace rtengine;
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void RawImageSource::CLASS cfa_linedn(float noise)
+void RawImageSource::CLASS cfa_linedn(float noise, bool horizontal, bool vertical)
{
// local variables
int height = H, width = W;
@@ -183,14 +183,14 @@ void RawImageSource::CLASS cfa_linedn(float noise)
}
//horizontal lines
- if (noisevarm4 > (linehvar[0] + linehvar[1])) { //horizontal lines
+ if (horizontal && noisevarm4 > (linehvar[0] + linehvar[1])) { //horizontal lines
for (int i = 1; i < 8; i++) {
dctblock[0][0][i] *= 0.5f * (noisefactor[0][i][1] + noisefactor[1][i][1]); //or should we use MIN???
dctblock[1][0][i] *= 0.5f * (noisefactor[0][i][1] + noisefactor[1][i][1]); //or should we use MIN???
}
}
- if (noisevarm4 > (linehvar[2] + linehvar[3])) { //horizontal lines
+ if (horizontal && noisevarm4 > (linehvar[2] + linehvar[3])) { //horizontal lines
for (int i = 1; i < 8; i++) {
dctblock[2][0][i] *= 0.5f * (noisefactor[2][i][1] + noisefactor[3][i][1]); //or should we use MIN???
dctblock[3][0][i] *= 0.5f * (noisefactor[2][i][1] + noisefactor[3][i][1]); //or should we use MIN???
@@ -198,14 +198,14 @@ void RawImageSource::CLASS cfa_linedn(float noise)
}
//vertical lines
- if (noisevarm4 > (linevvar[0] + linevvar[2])) { //vertical lines
+ if (vertical && noisevarm4 > (linevvar[0] + linevvar[2])) { //vertical lines
for (int i = 1; i < 8; i++) {
dctblock[0][i][0] *= 0.5f * (noisefactor[0][i][0] + noisefactor[2][i][0]); //or should we use MIN???
dctblock[2][i][0] *= 0.5f * (noisefactor[0][i][0] + noisefactor[2][i][0]); //or should we use MIN???
}
}
- if (noisevarm4 > (linevvar[1] + linevvar[3])) { //vertical lines
+ if (vertical && noisevarm4 > (linevvar[1] + linevvar[3])) { //vertical lines
for (int i = 1; i < 8; i++) {
dctblock[1][i][0] *= 0.5f * (noisefactor[1][i][0] + noisefactor[3][i][0]); //or should we use MIN???
dctblock[3][i][0] *= 0.5f * (noisefactor[1][i][0] + noisefactor[3][i][0]); //or should we use MIN???
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 35b176ba1..7d87aa2b8 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -2349,6 +2349,7 @@ RAWParams::BayerSensor::BayerSensor() :
black3(0.0),
twogreen(true),
linenoise(0),
+ linenoiseDirection(LineNoiseDirection::BOTH),
greenthresh(0),
dcb_iterations(2),
lmmse_iterations(2),
@@ -2399,6 +2400,7 @@ bool RAWParams::BayerSensor::operator ==(const BayerSensor& other) const
&& black3 == other.black3
&& twogreen == other.twogreen
&& linenoise == other.linenoise
+ && linenoiseDirection == other.linenoiseDirection
&& greenthresh == other.greenthresh
&& dcb_iterations == other.dcb_iterations
&& lmmse_iterations == other.lmmse_iterations
@@ -3366,6 +3368,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->raw.bayersensor.exBlack3, "RAW Bayer", "PreBlack3", raw.bayersensor.black3, keyFile);
saveToKeyfile(!pedited || pedited->raw.bayersensor.exTwoGreen, "RAW Bayer", "PreTwoGreen", raw.bayersensor.twogreen, keyFile);
saveToKeyfile(!pedited || pedited->raw.bayersensor.linenoise, "RAW Bayer", "LineDenoise", raw.bayersensor.linenoise, keyFile);
+ saveToKeyfile(!pedited || pedited->raw.bayersensor.linenoise, "RAW Bayer", "LineDenoiseDirection", toUnderlying(raw.bayersensor.linenoiseDirection), keyFile);
saveToKeyfile(!pedited || pedited->raw.bayersensor.greenEq, "RAW Bayer", "GreenEqThreshold", raw.bayersensor.greenthresh, keyFile);
saveToKeyfile(!pedited || pedited->raw.bayersensor.dcbIterations, "RAW Bayer", "DCBIterations", raw.bayersensor.dcb_iterations, keyFile);
saveToKeyfile(!pedited || pedited->raw.bayersensor.dcbEnhance, "RAW Bayer", "DCBEnhance", raw.bayersensor.dcb_enhance, keyFile);
@@ -4684,6 +4687,12 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "RAW Bayer", "PreBlack3", pedited, raw.bayersensor.black3, pedited->raw.bayersensor.exBlack3);
assignFromKeyfile(keyFile, "RAW Bayer", "PreTwoGreen", pedited, raw.bayersensor.twogreen, pedited->raw.bayersensor.exTwoGreen);
assignFromKeyfile(keyFile, "RAW Bayer", "LineDenoise", pedited, raw.bayersensor.linenoise, pedited->raw.bayersensor.linenoise);
+ if (keyFile.has_key("RAW Bayer", "LineDenoiseDirection")) {
+ raw.bayersensor.linenoiseDirection = RAWParams::BayerSensor::LineNoiseDirection(keyFile.get_integer("RAW Bayer", "LineDenoiseDirection"));
+ if (pedited) {
+ pedited->raw.bayersensor.linenoiseDirection = true;
+ }
+ }
assignFromKeyfile(keyFile, "RAW Bayer", "GreenEqThreshold", pedited, raw.bayersensor.greenthresh, pedited->raw.bayersensor.greenEq);
assignFromKeyfile(keyFile, "RAW Bayer", "DCBIterations", pedited, raw.bayersensor.dcb_iterations, pedited->raw.bayersensor.dcbIterations);
assignFromKeyfile(keyFile, "RAW Bayer", "DCBEnhance", pedited, raw.bayersensor.dcb_enhance, pedited->raw.bayersensor.dcbEnhance);
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index ee4c1756f..605db56ce 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -1260,6 +1260,12 @@ struct RAWParams {
double black3;
bool twogreen;
int linenoise;
+ enum class LineNoiseDirection {
+ HORIZONTAL = 1,
+ VERTICAL,
+ BOTH
+ };
+ LineNoiseDirection linenoiseDirection;
int greenthresh;
int dcb_iterations;
int lmmse_iterations;
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index aef4447ce..cb57591c2 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1969,7 +1969,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
plistener->setProgress (0.0);
}
- cfa_linedn(0.00002 * (raw.bayersensor.linenoise));
+ cfa_linedn(0.00002 * (raw.bayersensor.linenoise), int(raw.bayersensor.linenoiseDirection) & int(RAWParams::BayerSensor::LineNoiseDirection::VERTICAL), int(raw.bayersensor.linenoiseDirection) & int(RAWParams::BayerSensor::LineNoiseDirection::HORIZONTAL));
}
if ( (raw.ca_autocorrect || fabs(raw.cared) > 0.001 || fabs(raw.cablue) > 0.001) && ri->getSensorType() == ST_BAYER ) { // Auto CA correction disabled for X-Trans, for now...
diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h
index ff7d2c1f9..b9ab7a154 100644
--- a/rtengine/rawimagesource.h
+++ b/rtengine/rawimagesource.h
@@ -234,7 +234,7 @@ protected:
int interpolateBadPixelsXtrans( PixelsMap &bitmapBads );
int findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels );
- void cfa_linedn (float linenoiselevel);//Emil's line denoise
+ void cfa_linedn (float linenoiselevel, bool horizontal, bool vertical);//Emil's line denoise
void green_equilibrate_global (array2D &rawData);
void green_equilibrate (float greenthresh, array2D &rawData);//Emil's green equilibration
diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc
index 51a0cb62a..e6402efd0 100644
--- a/rtgui/bayerpreprocess.cc
+++ b/rtgui/bayerpreprocess.cc
@@ -18,6 +18,7 @@
*/
#include "bayerpreprocess.h"
#include "guiutils.h"
+#include "eventmapper.h"
#include
using namespace rtengine;
@@ -25,6 +26,9 @@ using namespace rtengine::procparams;
BayerPreProcess::BayerPreProcess () : FoldableToolPanel(this, "bayerpreprocess", M("TP_PREPROCESS_LABEL"), true)
{
+ auto m = ProcEventMapper::getInstance();
+ EvLineDenoiseDirection = m->newEvent(DARKFRAME, "HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION");
+
lineDenoise = Gtk::manage(new Adjuster (M("TP_PREPROCESS_LINEDENOISE"), 0, 1000, 1, 0));
lineDenoise->setAdjusterListener (this);
@@ -43,7 +47,19 @@ BayerPreProcess::BayerPreProcess () : FoldableToolPanel(this, "bayerpreprocess",
greenEqThreshold->show();
+ Gtk::HBox *hb = Gtk::manage(new Gtk::HBox());
+ hb->pack_start(*Gtk::manage(new Gtk::Label(M("TP_PREPROCESS_LINEDENOISE_DIRECTION") + ": ")), Gtk::PACK_SHRINK, 0);
+ lineDenoiseDirection = Gtk::manage(new MyComboBoxText());
+ lineDenoiseDirection->append(M("TP_PREPROCESS_LINEDENOISE_DIRECTION_HORIZONTAL"));
+ lineDenoiseDirection->append(M("TP_PREPROCESS_LINEDENOISE_DIRECTION_VERTICAL"));
+ lineDenoiseDirection->append(M("TP_PREPROCESS_LINEDENOISE_DIRECTION_BOTH"));
+ lineDenoiseDirection->show();
+ lineDenoiseDirection->signal_changed().connect(sigc::mem_fun(*this, &BayerPreProcess::lineDenoiseDirectionChanged));
+
+ hb->pack_start(*lineDenoiseDirection);
+
pack_start( *lineDenoise, Gtk::PACK_SHRINK, 4);
+ pack_start(*hb, Gtk::PACK_SHRINK, 4);
pack_start( *Gtk::manage (new Gtk::HSeparator()));
@@ -58,9 +74,13 @@ void BayerPreProcess::read(const rtengine::procparams::ProcParams* pp, const Par
if(pedited ) {
lineDenoise->setEditedState( pedited->raw.bayersensor.linenoise ? Edited : UnEdited );
greenEqThreshold->setEditedState( pedited->raw.bayersensor.greenEq ? Edited : UnEdited );
+ if (!pedited->raw.bayersensor.linenoiseDirection) {
+ lineDenoiseDirection->set_active(3);
+ }
}
lineDenoise->setValue (pp->raw.bayersensor.linenoise);
+ lineDenoiseDirection->set_active(int(pp->raw.bayersensor.linenoiseDirection)-1);
greenEqThreshold->setValue (pp->raw.bayersensor.greenthresh);
enableListener ();
@@ -69,11 +89,13 @@ void BayerPreProcess::read(const rtengine::procparams::ProcParams* pp, const Par
void BayerPreProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited)
{
pp->raw.bayersensor.linenoise = lineDenoise->getIntValue();
+ pp->raw.bayersensor.linenoiseDirection = RAWParams::BayerSensor::LineNoiseDirection(lineDenoiseDirection->get_active_row_number() + 1);
pp->raw.bayersensor.greenthresh = greenEqThreshold->getIntValue();
if (pedited) {
pedited->raw.bayersensor.linenoise = lineDenoise->getEditedState ();
pedited->raw.bayersensor.greenEq = greenEqThreshold->getEditedState ();
+ pedited->raw.bayersensor.linenoise = lineDenoiseDirection->get_active_row_number() != 3;
}
}
@@ -96,6 +118,9 @@ void BayerPreProcess::setBatchMode(bool batchMode)
ToolPanel::setBatchMode (batchMode);
lineDenoise->showEditedCB ();
greenEqThreshold->showEditedCB ();
+ if (batchMode) {
+ lineDenoiseDirection->append(M("GENERAL_UNCHANGED"));
+ }
}
void BayerPreProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited)
@@ -125,3 +150,11 @@ void BayerPreProcess::trimValues (rtengine::procparams::ProcParams* pp)
lineDenoise->trimValue(pp->raw.bayersensor.linenoise);
greenEqThreshold->trimValue(pp->raw.bayersensor.greenthresh);
}
+
+
+void BayerPreProcess::lineDenoiseDirectionChanged()
+{
+ if (listener) {
+ listener->panelChanged(EvLineDenoiseDirection, lineDenoiseDirection->get_active_text());
+ }
+}
diff --git a/rtgui/bayerpreprocess.h b/rtgui/bayerpreprocess.h
index 15b2ef7e5..4c28ff64d 100644
--- a/rtgui/bayerpreprocess.h
+++ b/rtgui/bayerpreprocess.h
@@ -30,8 +30,11 @@ class BayerPreProcess : public ToolParamBlock, public AdjusterListener, public F
protected:
Adjuster* lineDenoise;
+ MyComboBoxText *lineDenoiseDirection;
Adjuster* greenEqThreshold;
+ rtengine::ProcEvent EvLineDenoiseDirection;
+
public:
BayerPreProcess ();
@@ -45,6 +48,7 @@ public:
void hotDeadPixelChanged();
void setAdjusterBehavior (bool linedenoiseadd, bool greenequiladd);
void trimValues (rtengine::procparams::ProcParams* pp);
+ void lineDenoiseDirectionChanged();
};
#endif
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 0833da4e8..8acae08b3 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -433,6 +433,7 @@ void ParamsEdited::set (bool v)
raw.bayersensor.pixelShiftNonGreenAmaze = v;
raw.bayersensor.greenEq = v;
raw.bayersensor.linenoise = v;
+ raw.bayersensor.linenoiseDirection = v;
raw.xtranssensor.method = v;
raw.xtranssensor.ccSteps = v;
raw.xtranssensor.exBlackRed = v;
@@ -994,6 +995,7 @@ void ParamsEdited::initFrom (const std::vector
raw.bayersensor.pixelShiftNonGreenAmaze = raw.bayersensor.pixelShiftNonGreenAmaze && p.raw.bayersensor.pixelShiftNonGreenAmaze == other.raw.bayersensor.pixelShiftNonGreenAmaze;
raw.bayersensor.greenEq = raw.bayersensor.greenEq && p.raw.bayersensor.greenthresh == other.raw.bayersensor.greenthresh;
raw.bayersensor.linenoise = raw.bayersensor.linenoise && p.raw.bayersensor.linenoise == other.raw.bayersensor.linenoise;
+ raw.bayersensor.linenoiseDirection = raw.bayersensor.linenoiseDirection && p.raw.bayersensor.linenoiseDirection == other.raw.bayersensor.linenoiseDirection;
raw.xtranssensor.method = raw.xtranssensor.method && p.raw.xtranssensor.method == other.raw.xtranssensor.method;
raw.xtranssensor.ccSteps = raw.xtranssensor.ccSteps && p.raw.xtranssensor.ccSteps == other.raw.xtranssensor.ccSteps;
raw.xtranssensor.exBlackRed = raw.xtranssensor.exBlackRed && p.raw.xtranssensor.blackred == other.raw.xtranssensor.blackred;
@@ -2640,6 +2642,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
toEdit.raw.bayersensor.linenoise = dontforceSet && options.baBehav[ADDSET_PREPROCESS_LINEDENOISE] ? toEdit.raw.bayersensor.linenoise + mods.raw.bayersensor.linenoise : mods.raw.bayersensor.linenoise;
}
+ if (raw.bayersensor.linenoiseDirection) {
+ toEdit.raw.bayersensor.linenoiseDirection = mods.raw.bayersensor.linenoiseDirection;
+ }
+
if (raw.xtranssensor.method) {
toEdit.raw.xtranssensor.method = mods.raw.xtranssensor.method;
}
@@ -3148,7 +3154,7 @@ bool RAWParamsEdited::BayerSensor::isUnchanged() const
&& pixelShiftMotion && pixelShiftMotionCorrection && pixelShiftMotionCorrectionMethod && pixelShiftStddevFactorGreen && pixelShiftStddevFactorRed && pixelShiftStddevFactorBlue && pixelShiftEperIso
&& pixelShiftNreadIso && pixelShiftPrnu && pixelShiftSigma && pixelShiftSum && pixelShiftRedBlueWeight && pixelShiftShowMotion && pixelShiftShowMotionMaskOnly
&& pixelShiftAutomatic && pixelShiftNonGreenHorizontal && pixelShiftNonGreenVertical && pixelShiftHoleFill && pixelShiftMedian && pixelShiftMedian3 && pixelShiftNonGreenCross && pixelShiftNonGreenCross2 && pixelShiftNonGreenAmaze && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftExp0 && pixelShiftLmmse && pixelShiftOneGreen && pixelShiftEqualBright && pixelShiftEqualBrightChannel
- && linenoise && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen;
+ && linenoise && linenoiseDirection && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen;
}
bool RAWParamsEdited::XTransSensor::isUnchanged() const
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index ad0b15e8c..d77e06b2d 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -763,6 +763,7 @@ public:
//bool allEnhance;
bool greenEq;
bool linenoise;
+ bool linenoiseDirection;
bool isUnchanged() const;
};
diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc
index 27a56e38e..6ff9f4d3b 100644
--- a/rtgui/partialpastedlg.cc
+++ b/rtgui/partialpastedlg.cc
@@ -875,6 +875,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
if (!raw_linenoise->get_active ()) {
filterPE.raw.bayersensor.linenoise = falsePE.raw.bayersensor.linenoise;
+ filterPE.raw.bayersensor.linenoiseDirection = falsePE.raw.bayersensor.linenoiseDirection;
}
if (!raw_greenthresh->get_active ()) {