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