diff --git a/rtdata/languages/default b/rtdata/languages/default
index dcd6fd3da..68386d1bd 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -700,8 +700,9 @@ HISTORY_MSG_465;EvPixelShiftSum
HISTORY_MSG_466;EvPixelShiftExp0
HISTORY_MSG_467;EvPixelShiftHoleFill
HISTORY_MSG_468;EvPixelShiftMedian
-HISTORY_MSG_469;EvPixelShiftMotionMethod
-HISTORY_MSG_470;EvPixelShiftSmooth
+HISTORY_MSG_469;EvPixelShiftMedian3
+HISTORY_MSG_470;EvPixelShiftMotionMethod
+HISTORY_MSG_471;EvPixelShiftSmooth
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -1702,7 +1703,7 @@ TP_RAW_PIXELSHIFTMOTION;Motion detection level (deprecated)
TP_RAW_PIXELSHIFTMOTION_TOOLTIP;0 means no motion detection\n1 - 99 means motion will be detected according to this value. Increase value to increase detection rate\n100 means the Amaze demosaiced frame will be used
TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP;Fill holes in motion mask
TP_RAW_PIXELSHIFTBLUR_TOOLTIP;Blur motion mask
-TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP;Smooth transitions (requires 3x3 new Blur)
+TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP;Smooth transitions (requires 3x3 new Blur)\nSet to 0 to disable smooth transitions\nSet to 1 to get Amaze or Median
TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP;Use median of all frames instead of selected frame for regions with motion.\nRemoves objects which are at different places in all frames.\nGives motion effect on slow moving (overlapping) objects.
TP_RAW_PIXELSHIFTMEDIAN3_TOOLTIP;Excludes selected frame from median.\nUseful if moving objects overlap in frame 2 and 3
TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP;Overlays the image with a mask showing the regions with motion
diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc
index 91aa972ee..188b5f4bf 100644
--- a/rtengine/pixelshift.cc
+++ b/rtengine/pixelshift.cc
@@ -906,7 +906,8 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
const float threshold = bayerParams.pixelShiftSum;
const bool experimental0 = bayerParams.pixelShiftExp0;
const bool holeFill = bayerParams.pixelShiftHoleFill;
- const bool smoothTransitions = blurMap && bayerParams.pixelShiftSmooth;
+ const bool smoothTransitions = blurMap && bayerParams.pixelShiftSmoothFactor > 0.;
+ const float smoothFactor = 1.0 - bayerParams.pixelShiftSmoothFactor;
static const float nReadK3II[] = { 3.4f, // ISO 100
3.1f, // ISO 125
@@ -1638,12 +1639,34 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
#pragma omp parallel for schedule(dynamic,16)
for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) {
+#ifdef __SSE2__
+ if(!(showMotion && showOnlyMask) && smoothTransitions) {
+ if(smoothFactor == 0.f) {
+ for(int j = winx + border - offsX; j < winw - (border + offsX); ++j) {
+ psMask[i][j] = 1.f;
+ }
+ } else {
+ vfloat zerov = F2V(0.f);
+ vfloat smoothv = F2V(smoothFactor);
+ int j = winx + border - offsX;
+ for(; j < winw - (border + offsX)- 3; j += 4) {
+ vfloat blendv = LVFU(psMask[i][j]);
+ blendv = vmaxf(blendv, zerov);
+ blendv = pow_F(blendv, smoothv);
+ STVFU(psMask[i][j], blendv);
+ }
+ for(; j < winw - (border + offsX); ++j) {
+ psMask[i][j] = pow_F(std::max(psMask[i][j],0.f),smoothFactor);
+ }
+ }
+ }
+#endif
float *greenDest = green[i + offsY];
float *redDest = red[i + offsY];
float *blueDest = blue[i + offsY];
for(int j = winx + border - offsX; j < winw - (border + offsX); ++j) {
- if(mask[i][j] == 255 ) {
+ if(mask[i][j] == 255) {
paintMotionMask(j + offsX, showMotion, 0.5f, showOnlyMask, greenDest, redDest, blueDest);
continue;
}
@@ -1652,9 +1675,14 @@ void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RA
red[i + offsY][j + offsX] = green[i + offsY][j + offsX] = blue[i + offsY][j + offsX] = 0.f;
} else {
if(smoothTransitions) {
- red[i + offsY][j + offsX] = intp(psMask[i][j], red[i + offsY][j + offsX], psRed[i][j] );
- green[i + offsY][j + offsX] = intp(psMask[i][j],green[i + offsY][j + offsX],(psG1[i][j] + psG2[i][j]) / 2.f);
- blue[i + offsY][j + offsX] = intp(psMask[i][j],blue[i + offsY][j + offsX], psBlue[i][j]);
+#ifdef __SSE2__
+ float blend = psMask[i][j];
+#else
+ float blend = pow_F(std::max(psMask[i][j],0.f),smoothFactor);
+#endif
+ red[i + offsY][j + offsX] = intp(blend, red[i + offsY][j + offsX], psRed[i][j] );
+ green[i + offsY][j + offsX] = intp(blend, green[i + offsY][j + offsX],(psG1[i][j] + psG2[i][j]) / 2.f);
+ blue[i + offsY][j + offsX] = intp(blend, blue[i + offsY][j + offsX], psBlue[i][j]);
} else {
red[i + offsY][j + offsX] = psRed[i][j];
green[i + offsY][j + offsX] = (psG1[i][j] + psG2[i][j]) / 2.f;
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 2edf7c77e..d0a79e6a8 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -897,7 +897,7 @@ void RAWParams::BayerSensor::setPixelShiftDefaults()
pixelShiftMedian3 = false;
pixelShiftGreen = true;
pixelShiftBlur = true;
- pixelShiftSmooth = true;
+ pixelShiftSmoothFactor = 0.7;
pixelShiftExp0 = false;
pixelShiftNonGreenCross = true;
pixelShiftNonGreenCross2 = false;
@@ -3485,7 +3485,7 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b
}
if (!pedited || pedited->raw.bayersensor.pixelShiftSmooth) {
- keyFile.set_boolean ("RAW Bayer", "pixelShiftSmooth", raw.bayersensor.pixelShiftSmooth );
+ keyFile.set_double ("RAW Bayer", "pixelShiftSmoothFactor", raw.bayersensor.pixelShiftSmoothFactor );
}
if (!pedited || pedited->raw.bayersensor.pixelShiftExp0) {
@@ -7736,8 +7736,8 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited)
}
}
- if (keyFile.has_key ("RAW Bayer", "pixelShiftSmooth")) {
- raw.bayersensor.pixelShiftSmooth = keyFile.get_boolean("RAW Bayer", "pixelShiftSmooth");
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftSmoothFactor")) {
+ raw.bayersensor.pixelShiftSmoothFactor = keyFile.get_double("RAW Bayer", "pixelShiftSmoothFactor");
if (pedited) {
pedited->raw.bayersensor.pixelShiftSmooth = true;
@@ -8235,7 +8235,7 @@ bool ProcParams::operator== (const ProcParams& other)
&& raw.bayersensor.pixelShiftMedian3 == other.raw.bayersensor.pixelShiftMedian3
&& raw.bayersensor.pixelShiftGreen == other.raw.bayersensor.pixelShiftGreen
&& raw.bayersensor.pixelShiftBlur == other.raw.bayersensor.pixelShiftBlur
- && raw.bayersensor.pixelShiftSmooth == other.raw.bayersensor.pixelShiftSmooth
+ && raw.bayersensor.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor
&& raw.bayersensor.pixelShiftExp0 == other.raw.bayersensor.pixelShiftExp0
&& raw.bayersensor.pixelShiftNonGreenCross == other.raw.bayersensor.pixelShiftNonGreenCross
&& raw.bayersensor.pixelShiftNonGreenCross2 == other.raw.bayersensor.pixelShiftNonGreenCross2
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index dbf285fb2..21fe97855 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -1229,7 +1229,7 @@ public:
bool pixelShiftMedian3;
bool pixelShiftGreen;
bool pixelShiftBlur;
- bool pixelShiftSmooth;
+ double pixelShiftSmoothFactor;
bool pixelShiftExp0;
bool pixelShiftNonGreenCross;
bool pixelShiftNonGreenCross2;
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index f5bea64d3..e5cce8f57 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -2035,7 +2035,7 @@ void RawImageSource::demosaic(const RAWParams &raw)
bayerParams.pixelShiftAutomatic = false;
bayerParams.pixelshiftShowMotion = false;
}
- if(!bayerParams.pixelshiftShowMotion || bayerParams.pixelShiftNonGreenAmaze || bayerParams.pixelShiftNonGreenCross2 || (bayerParams.pixelShiftBlur && bayerParams.pixelShiftSmooth)) {
+ if(!bayerParams.pixelshiftShowMotion || bayerParams.pixelShiftNonGreenAmaze || bayerParams.pixelShiftNonGreenCross2 || (bayerParams.pixelShiftBlur && bayerParams.pixelShiftSmoothFactor > 0.0)) {
if((bayerParams.pixelShiftMotion > 0 || bayerParams.pixelShiftAutomatic) && numFrames == 4) {
if(bayerParams.pixelShiftMedian) { // We need the amaze demosaiced frames for motion correction
if(!bayerParams.pixelShiftMedian3) {
diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc
index 89b92ebd2..8c2b8da48 100644
--- a/rtgui/bayerprocess.cc
+++ b/rtgui/bayerprocess.cc
@@ -128,8 +128,15 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA
pixelShiftBlur->set_tooltip_text (M("TP_RAW_PIXELSHIFTBLUR_TOOLTIP"));
pixelShiftOptions->pack_start(*pixelShiftBlur);
- pixelShiftSmooth = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_PIXELSHIFTSMOOTH")));
+ pixelShiftSmooth = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSMOOTH"), 0, 1, 0.05, 0.7));
pixelShiftSmooth->set_tooltip_text (M("TP_RAW_PIXELSHIFTSMOOTH_TOOLTIP"));
+ pixelShiftSmooth->setAdjusterListener (this);
+
+ if (pixelShiftSmooth->delay < options.adjusterMaxDelay) {
+ pixelShiftSmooth->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftSmooth->show();
pixelShiftOptions->pack_start(*pixelShiftSmooth);
pixelShiftHoleFill = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_PIXELSHIFTHOLEFILL")));
@@ -305,7 +312,6 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA
pixelShiftMedian3conn = pixelShiftMedian3->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftMedian3Changed), true);
pixelShiftGreenconn = pixelShiftGreen->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftGreenChanged), true);
pixelShiftBlurconn = pixelShiftBlur->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftBlurChanged), true);
- pixelShiftSmoothconn = pixelShiftSmooth->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftSmoothChanged), true);
pixelShiftExp0conn = pixelShiftExp0->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftExp0Changed), true);
pixelShiftNonGreenCrossconn = pixelShiftNonGreenCross->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftNonGreenCrossChanged), true);
pixelShiftNonGreenCross2conn = pixelShiftNonGreenCross2->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftNonGreenCross2Changed), true);
@@ -347,7 +353,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params
pixelShiftMedian3->set_inconsistent(!pedited->raw.bayersensor.pixelShiftMedian3);
pixelShiftGreen->set_inconsistent(!pedited->raw.bayersensor.pixelShiftGreen);
pixelShiftBlur->set_inconsistent(!pedited->raw.bayersensor.pixelShiftBlur);
- pixelShiftSmooth->set_inconsistent(!pedited->raw.bayersensor.pixelShiftSmooth);
+ pixelShiftSmooth->setEditedState ( pedited->raw.bayersensor.pixelShiftSmooth ? Edited : UnEdited);
pixelShiftExp0->set_inconsistent(!pedited->raw.bayersensor.pixelShiftExp0);
pixelShiftNonGreenCross->set_inconsistent(!pedited->raw.bayersensor.pixelShiftNonGreenCross);
pixelShiftNonGreenCross2->set_inconsistent(!pedited->raw.bayersensor.pixelShiftNonGreenCross2);
@@ -392,7 +398,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params
pixelShiftMedian3->set_active(pp->raw.bayersensor.pixelShiftMedian3);
pixelShiftGreen->set_active(pp->raw.bayersensor.pixelShiftGreen);
pixelShiftBlur->set_active(pp->raw.bayersensor.pixelShiftBlur);
- pixelShiftSmooth->set_active(pp->raw.bayersensor.pixelShiftSmooth);
+ pixelShiftSmooth->setValue (pp->raw.bayersensor.pixelShiftSmoothFactor);
pixelShiftExp0->set_active(pp->raw.bayersensor.pixelShiftExp0);
pixelShiftNonGreenCross->set_active(pp->raw.bayersensor.pixelShiftNonGreenCross);
pixelShiftNonGreenCross2->set_active(pp->raw.bayersensor.pixelShiftNonGreenCross2);
@@ -491,7 +497,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe
pp->raw.bayersensor.pixelShiftMedian3 = pixelShiftMedian3->get_active();
pp->raw.bayersensor.pixelShiftGreen = pixelShiftGreen->get_active();
pp->raw.bayersensor.pixelShiftBlur = pixelShiftBlur->get_active();
- pp->raw.bayersensor.pixelShiftSmooth = pixelShiftSmooth->get_active();
+ pp->raw.bayersensor.pixelShiftSmoothFactor = pixelShiftSmooth->getValue();
pp->raw.bayersensor.pixelShiftExp0 = pixelShiftExp0->get_active();
pp->raw.bayersensor.pixelShiftNonGreenCross = pixelShiftNonGreenCross->get_active();
pp->raw.bayersensor.pixelShiftNonGreenCross2 = pixelShiftNonGreenCross2->get_active();
@@ -538,7 +544,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe
pedited->raw.bayersensor.pixelShiftMedian3 = !pixelShiftMedian3->get_inconsistent();
pedited->raw.bayersensor.pixelShiftGreen = !pixelShiftGreen->get_inconsistent();
pedited->raw.bayersensor.pixelShiftBlur = !pixelShiftBlur->get_inconsistent();
- pedited->raw.bayersensor.pixelShiftSmooth = !pixelShiftSmooth->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftSmooth = pixelShiftSmooth->getEditedState();
pedited->raw.bayersensor.pixelShiftExp0 = !pixelShiftExp0->get_inconsistent();
pedited->raw.bayersensor.pixelShiftNonGreenCross = !pixelShiftNonGreenCross->get_inconsistent();
pedited->raw.bayersensor.pixelShiftNonGreenCross2 = !pixelShiftNonGreenCross2->get_inconsistent();
@@ -651,6 +657,8 @@ void BayerProcess::adjusterChanged (Adjuster* a, double newval)
listener->panelChanged (EvPixelShiftSum, a->getTextValue() );
} else if (a == pixelShiftRedBlueWeight) {
listener->panelChanged (EvPixelShiftRedBlueWeight, a->getTextValue() );
+ } else if (a == pixelShiftSmooth) {
+ listener->panelChanged (EvPixelShiftSmooth, a->getTextValue() );
}
}
}
@@ -990,26 +998,6 @@ void BayerProcess::pixelShiftBlurChanged ()
}
}
-void BayerProcess::pixelShiftSmoothChanged ()
-{
- if (batchMode) {
- if (pixelShiftSmooth->get_inconsistent()) {
- pixelShiftSmooth->set_inconsistent (false);
- pixelShiftSmoothconn.block (true);
- pixelShiftSmooth->set_active (false);
- pixelShiftSmoothconn.block (false);
- } else if (lastDCBen) {
- pixelShiftSmooth->set_inconsistent (true);
- }
-
- lastDCBen = pixelShiftSmooth->get_active ();
- }
-
- if (listener) {
- listener->panelChanged (EvPixelShiftSmooth, pixelShiftSmooth->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
- }
-}
-
void BayerProcess::pixelShiftExp0Changed ()
{
if (batchMode) {
diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h
index 135c02df5..def4021ce 100644
--- a/rtgui/bayerprocess.h
+++ b/rtgui/bayerprocess.h
@@ -56,11 +56,11 @@ protected:
Gtk::CheckButton* pixelShiftNonGreenAmaze;
Gtk::CheckButton* pixelShiftGreen;
Gtk::CheckButton* pixelShiftBlur;
- Gtk::CheckButton* pixelShiftSmooth;
Gtk::CheckButton* pixelShiftExp0;
Gtk::CheckButton* pixelShiftHoleFill;
Gtk::CheckButton* pixelShiftMedian;
Gtk::CheckButton* pixelShiftMedian3;
+ Adjuster* pixelShiftSmooth;
Adjuster* pixelShiftStddevFactorGreen;
Adjuster* pixelShiftStddevFactorRed;
Adjuster* pixelShiftStddevFactorBlue;
@@ -101,7 +101,6 @@ public:
void pixelShiftMedian3Changed();
void pixelShiftGreenChanged();
void pixelShiftBlurChanged();
- void pixelShiftSmoothChanged();
void pixelShiftExp0Changed();
void pixelShiftNonGreenCrossChanged();
void pixelShiftNonGreenCross2Changed();
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 061424acf..e1303095a 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -915,7 +915,7 @@ void ParamsEdited::initFrom (const std::vector
raw.bayersensor.pixelShiftMedian3 = raw.bayersensor.pixelShiftMedian3 && p.raw.bayersensor.pixelShiftMedian3 == other.raw.bayersensor.pixelShiftMedian3;
raw.bayersensor.pixelShiftGreen = raw.bayersensor.pixelShiftGreen && p.raw.bayersensor.pixelShiftGreen == other.raw.bayersensor.pixelShiftGreen;
raw.bayersensor.pixelShiftBlur = raw.bayersensor.pixelShiftBlur && p.raw.bayersensor.pixelShiftBlur == other.raw.bayersensor.pixelShiftBlur;
- raw.bayersensor.pixelShiftSmooth = raw.bayersensor.pixelShiftSmooth && p.raw.bayersensor.pixelShiftSmooth == other.raw.bayersensor.pixelShiftSmooth;
+ raw.bayersensor.pixelShiftSmooth = raw.bayersensor.pixelShiftSmooth && p.raw.bayersensor.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor;
raw.bayersensor.pixelShiftExp0 = raw.bayersensor.pixelShiftExp0 && p.raw.bayersensor.pixelShiftExp0 == other.raw.bayersensor.pixelShiftExp0;
raw.bayersensor.pixelShiftNonGreenCross = raw.bayersensor.pixelShiftNonGreenCross && p.raw.bayersensor.pixelShiftNonGreenCross == other.raw.bayersensor.pixelShiftNonGreenCross;
raw.bayersensor.pixelShiftNonGreenCross2 = raw.bayersensor.pixelShiftNonGreenCross2 && p.raw.bayersensor.pixelShiftNonGreenCross2 == other.raw.bayersensor.pixelShiftNonGreenCross2;
@@ -2421,7 +2421,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
}
if (raw.bayersensor.pixelShiftSmooth) {
- toEdit.raw.bayersensor.pixelShiftSmooth = mods.raw.bayersensor.pixelShiftSmooth;
+ toEdit.raw.bayersensor.pixelShiftSmoothFactor = mods.raw.bayersensor.pixelShiftSmoothFactor;
}
if (raw.bayersensor.pixelShiftExp0) {