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