diff --git a/AUTHORS.txt b/AUTHORS.txt
index 3dc820555..0ad8438eb 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -46,6 +46,7 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati
André Gauthier
Sébastien Guyader
M. Dávid Gyurkó
+ JK Han (pinholecam)
Arturs Jekabsons
Marián Kyral
Oscar de Lama
@@ -56,6 +57,8 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati
Wim ter Meer
Alberto Righetto
Kostia (Kildor) Romanov
+ Kalle Söderman
Johan Thor
+ Vitalis Tiknius
TooWaBoo
Colin Walker
diff --git a/rtdata/languages/default b/rtdata/languages/default
index ec61230ff..02260f2e5 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -685,6 +685,36 @@ HISTORY_MSG_441;Retinex - Gain transmission
HISTORY_MSG_442;Retinex - Scale
HISTORY_MSG_443;Output Black Point Compensation
HISTORY_MSG_444;WB - Temp bias
+HISTORY_MSG_445;Raw Sub-Image
+HISTORY_MSG_446;EvPixelShiftMotion
+HISTORY_MSG_447;EvPixelShiftMotionCorrection
+HISTORY_MSG_448;EvPixelShiftStddevFactorGreen
+HISTORY_MSG_449;PS ISO adaption
+HISTORY_MSG_450;EvPixelShiftNreadIso
+HISTORY_MSG_451;EvPixelShiftPrnu
+HISTORY_MSG_452;PS Show motion
+HISTORY_MSG_453;PS Show mask only
+HISTORY_MSG_454;EvPixelShiftAutomatic
+HISTORY_MSG_455;EvPixelShiftNonGreenHorizontal
+HISTORY_MSG_456;EvPixelShiftNonGreenVertical
+HISTORY_MSG_457;PS Check red/blue
+HISTORY_MSG_458;EvPixelShiftStddevFactorRed
+HISTORY_MSG_459;EvPixelShiftStddevFactorBlue
+HISTORY_MSG_460;EvPixelShiftGreenAmaze
+HISTORY_MSG_461;EvPixelShiftNonGreenAmaze
+HISTORY_MSG_462;PS Check green
+HISTORY_MSG_463;EvPixelShiftRedBlueWeight
+HISTORY_MSG_464;PS Blur motion mask
+HISTORY_MSG_465;PS Blur radius
+HISTORY_MSG_466;EvPixelShiftSum
+HISTORY_MSG_467;EvPixelShiftExp0
+HISTORY_MSG_468;PS Fill holes
+HISTORY_MSG_469;PS Median
+HISTORY_MSG_470;EvPixelShiftMedian3
+HISTORY_MSG_471;PS Motion correction
+HISTORY_MSG_472;PS Smooth transitions
+HISTORY_MSG_473;PS Use lmmse
+HISTORY_MSG_474;PS Equalize
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -875,6 +905,7 @@ PARTIALPASTE_RAW_DCBENHANCE;DCB enhancement
PARTIALPASTE_RAW_DCBITERATIONS;DCB iterations
PARTIALPASTE_RAW_DMETHOD;Demosaic method
PARTIALPASTE_RAW_FALSECOLOR;False color suppression
+PARTIALPASTE_RAW_IMAGENUM;Sub-image
PARTIALPASTE_RAW_LMMSEITERATIONS;LMMSE enhancement steps
PARTIALPASTE_RESIZE;Resize
PARTIALPASTE_RETINEX;Retinex
@@ -1660,13 +1691,57 @@ TP_RAW_DCBITERATIONS;Number of DCB iterations
TP_RAW_DMETHOD;Method
TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing...
TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement...
-TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.
+TP_RAW_DMETHOD_TOOLTIP;Note: IGV and LMMSE are dedicated to high ISO images to aid in noise reduction without leading to maze patterns, posterization or a washed-out look.\nPixelshift is for Pentax pixelshift files. It falls back to Amaze for non pixelshift files.
TP_RAW_FALSECOLOR;False color suppression steps
TP_RAW_HD;Threshold
TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, but false positives may lead to artifacts. If you notice any artifacts appearing when enabling the Hot/Dead Pixel Filters, gradually increase the threshold value until they disappear.
+TP_RAW_IMAGENUM;Sub-image
+TP_RAW_IMAGENUM_TOOLTIP;Some raw files might embed several sub-images (HDR, Pixel-Shift, Dual Sensitivity). Use this button to select the sub-image.\n\nThe last sub-image will be used if you select a value beyond the real sub-image count.
TP_RAW_LABEL;Demosaicing
TP_RAW_LMMSEITERATIONS;LMMSE enhancement steps
TP_RAW_LMMSE_TOOLTIP;Adds gamma (step 1), median (steps 2-4) and refinement (steps 5-6) to reduce artifacts and improve the signal-to-noise ratio.
+TP_RAW_PIXELSHIFTADAPTIVE;Adaptive detection
+TP_RAW_PIXELSHIFTNONGREENHORIZONTAL;Check red/blue horizontal
+TP_RAW_PIXELSHIFTNONGREENVERTICAL;Check red/blue vertical
+TP_RAW_PIXELSHIFTMEDIAN;Median
+TP_RAW_PIXELSHIFTMEDIAN3;Exclude selected frame from median
+TP_RAW_PIXELSHIFTHOLEFILL;Fill holes in motion mask
+TP_RAW_PIXELSHIFTBLUR;Blur motion mask
+TP_RAW_PIXELSHIFTSIGMA_TOOLTIP;Default radius of 1.0 usually fits good for base ISO. Increase value for high ISO shots,\n5.0 is a good starting point for high ISO shots.\nWatch motion mask while changing the value.
+TP_RAW_PIXELSHIFTSMOOTH;Smooth transitions
+TP_RAW_PIXELSHIFTLMMSE_TOOLTIP;Use lmmse instead of amaze for motion areas.\nUseful for High ISO images.
+TP_RAW_PIXELSHIFTLMMSE;Use lmmse for motion parts
+TP_RAW_PIXELSHIFTEQUALBRIGHT;Equalize brightness of frames
+TP_RAW_PIXELSHIFTEQUALBRIGHT_TOOLTIP;Equalize the brightness of the frames to the brightness of the selected frame.\nIf there are overexposed areas in the frames select the brightest frame to avoid magenta colour cast in overexposed areas or enable motion correction.
+TP_RAW_PIXELSHIFTEXP0;Experimental
+TP_RAW_PIXELSHIFTGREEN;Check green channel for motion
+TP_RAW_PIXELSHIFTNONGREENCROSS;Check red/blue channels for motion
+TP_RAW_PIXELSHIFTNONGREENCROSS2;Check green amaze
+TP_RAW_PIXELSHIFTNONGREENAMAZE;Check red/blue amaze
+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 between areas with and without motion.\nSet to 0 to disable smooth transitions\nSet to 1 to get Amaze/lmmse 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
+TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP;Shows the motion mask without the image
+TP_RAW_PIXELSHIFTMOTIONCORRECTION;Green motion correction size
+TP_RAW_PIXELSHIFTMOTIONCORRECTION_TOOLTIP;1 = 2 pixels\n3 = 3x3 grid\n5 = 5x5 grid
+TP_RAW_PIXELSHIFTMOTIONMETHOD;Motion Correction
+TP_RAW_PIXELSHIFTSHOWMOTION;Show motion
+TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY;Show mask only
+TP_RAW_PIXELSHIFTSTDDEVFACTORGREEN;StdDev factor Green
+TP_RAW_PIXELSHIFTSTDDEVFACTORRED;StdDev factor Red
+TP_RAW_PIXELSHIFTSTDDEVFACTORBLUE;StdDev factor Blue
+TP_RAW_PIXELSHIFTEPERISO;ISO adaption
+TP_RAW_PIXELSHIFTEPERISO_TOOLTIP;The default value (0.0) should work fine for base ISO.\nIncrease the value to improve motion detection for higher ISO.\nIncrease in small steps and watch the motion mask while increasing.
+TP_RAW_PIXELSHIFTNREADISO;nRead
+TP_RAW_PIXELSHIFTPRNU;PRNU (%)
+TP_RAW_PIXELSHIFTSIGMA;Blur radius
+TP_RAW_PIXELSHIFTMASKTHRESHOLD;3x3 new threshold
+TP_RAW_PIXELSHIFTREDBLUEWEIGHT;Red&Blue weight
TP_RAW_SENSOR_BAYER_LABEL;Sensor with Bayer Matrix
TP_RAW_SENSOR_XTRANS_DMETHOD_TOOLTIP;3-pass gives best results (recommended for low ISO images).\n1-pass is almost undistinguishable from 3-pass for high ISO images and is faster.
TP_RAW_SENSOR_XTRANS_LABEL;Sensor with X-Trans Matrix
diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc
index 7c28801ae..97450a61a 100644
--- a/rtengine/CA_correct_RT.cc
+++ b/rtengine/CA_correct_RT.cc
@@ -112,7 +112,7 @@ bool LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution)
using namespace std;
using namespace rtengine;
-void RawImageSource::CA_correct_RT(const double cared, const double cablue, const double caautostrength)
+void RawImageSource::CA_correct_RT(const double cared, const double cablue, const double caautostrength, array2D &rawData)
{
// multithreaded and partly vectorized by Ingo Weyrich
constexpr int ts = 128;
diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index dbab1dc2d..b52562e2b 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -24,6 +24,7 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc
klt/storeFeatures.cc klt/trackFeatures.cc klt/writeFeatures.cc
clutstore.cc
ciecam02.cc
+ pixelshift.cc
)
include_directories (BEFORE "${CMAKE_CURRENT_BINARY_DIR}")
diff --git a/rtengine/amaze_demosaic_RT.cc b/rtengine/amaze_demosaic_RT.cc
index c5535493c..3cb0ee8de 100644
--- a/rtengine/amaze_demosaic_RT.cc
+++ b/rtengine/amaze_demosaic_RT.cc
@@ -38,7 +38,7 @@
namespace rtengine
{
-SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh)
+SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue)
{
BENCHFUN
diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc
index 286574e0f..c1d2e670a 100644
--- a/rtengine/dcraw.cc
+++ b/rtengine/dcraw.cc
@@ -8578,7 +8578,7 @@ void CLASS identify()
parse_fuji (i);
}
load_raw = &CLASS unpacked_load_raw;
- fseek (ifp, 100+28*(shot_select > 0), SEEK_SET);
+ fseek (ifp, 100+28*(shot_select > 0 && shot_select < is_raw), SEEK_SET);
parse_tiff (data_offset = get4());
parse_tiff (thumb_offset+12);
/*RT*/ exif_base = thumb_offset+12;
@@ -9492,7 +9492,7 @@ dng_skip:
adobe_coeff (make, model);
if(!strncmp(make, "Samsung", 7) && !strncmp(model, "NX1",3))
adobe_coeff (make, model);
- if(!strncmp(make, "Pentax", 6) && (!strncmp(model, "K10D",4) || !strncmp(model, "K-70",4)))
+ if(!strncmp(make, "Pentax", 6) && (!strncmp(model, "K10D",4) || !strncmp(model, "K-70",4) || !strncmp(model, "K-1",3)))
adobe_coeff (make, model);
if(!strncmp(make, "Leica", 5) && !strncmp(model, "Q",1))
adobe_coeff (make, model);
diff --git a/rtengine/dcraw.patch b/rtengine/dcraw.patch
index 22c53d831..43f9e12eb 100644
--- a/rtengine/dcraw.patch
+++ b/rtengine/dcraw.patch
@@ -1,5 +1,5 @@
---- dcraw.c 2016-10-28 13:45:27 +0000
-+++ dcraw.cc 2016-10-31 13:35:15 +0000
+--- dcraw.c 2016-11-01 01:07:55 +0000
++++ dcraw.cc 2016-11-01 14:54:02 +0000
@@ -1,3 +1,16 @@
+/*RT*/#include
+/*RT*/#include
@@ -2892,8 +2892,12 @@
parse_ciff (hlen, flen-hlen, 0);
load_raw = &CLASS canon_load_raw;
} else if (parse_tiff(0)) apply_tiff();
-@@ -8494,6 +8575,7 @@
- fseek (ifp, 100+28*(shot_select > 0), SEEK_SET);
+@@ -8491,9 +8572,10 @@
+ parse_fuji (i);
+ }
+ load_raw = &CLASS unpacked_load_raw;
+- fseek (ifp, 100+28*(shot_select > 0), SEEK_SET);
++ fseek (ifp, 100+28*(shot_select > 0 && shot_select < is_raw), SEEK_SET);
parse_tiff (data_offset = get4());
parse_tiff (thumb_offset+12);
+/*RT*/ exif_base = thumb_offset+12;
diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc
index 60abe8998..877df35a4 100644
--- a/rtengine/demosaic_algos.cc
+++ b/rtengine/demosaic_algos.cc
@@ -1316,7 +1316,7 @@ void RawImageSource::jdl_interpolate_omp() // from "Lassus"
// Adapted to RawTherapee by Jacques Desmis 3/2013
// Improved speed and reduced memory consumption by Ingo Weyrich 2/2015
//TODO Tiles to reduce memory consumption
-SSEFUNCTION void RawImageSource::lmmse_interpolate_omp(int winw, int winh, int iterations)
+SSEFUNCTION void RawImageSource::lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations)
{
const int width = winw, height = winh;
const int ba = 10;
diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc
index 728d40d53..c71d7f98b 100644
--- a/rtengine/dfmanager.cc
+++ b/rtengine/dfmanager.cc
@@ -144,7 +144,7 @@ void dfInfo::updateRawImage()
} else {
int H = ri->get_height();
int W = ri->get_width();
- ri->compress_image();
+ ri->compress_image(0);
int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) ? 1 : 3);
acc_t **acc = new acc_t*[H];
@@ -164,7 +164,7 @@ void dfInfo::updateRawImage()
RawImage* temp = new RawImage(*iName);
if( !temp->loadRaw(true)) {
- temp->compress_image(); //\ TODO would be better working on original, because is temporary
+ temp->compress_image(0); //\ TODO would be better working on original, because is temporary
nFiles++;
if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS ) {
@@ -204,7 +204,7 @@ void dfInfo::updateRawImage()
delete ri;
ri = nullptr;
} else {
- ri->compress_image();
+ ri->compress_image(0);
}
}
}
diff --git a/rtengine/expo_before_b.cc b/rtengine/expo_before_b.cc
index 0854647c5..98fed04f7 100644
--- a/rtengine/expo_before_b.cc
+++ b/rtengine/expo_before_b.cc
@@ -44,7 +44,7 @@ namespace rtengine
extern const Settings* settings;
-void RawImageSource::processRawWhitepoint(float expos, float preser)
+void RawImageSource::processRawWhitepoint(float expos, float preser, array2D &rawData)
{
MyTime t1e, t2e;
diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc
index 069bbf563..87ae98905 100644
--- a/rtengine/ffmanager.cc
+++ b/rtengine/ffmanager.cc
@@ -130,14 +130,13 @@ void ffInfo::updateRawImage()
if( !pathNames.empty() ) {
std::list::iterator iName = pathNames.begin();
ri = new RawImage(*iName); // First file used also for extra pixels informations (width,height, shutter, filters etc.. )
-
if( ri->loadRaw(true)) {
delete ri;
ri = nullptr;
} else {
int H = ri->get_height();
int W = ri->get_width();
- ri->compress_image();
+ ri->compress_image(0);
int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) ? 1 : 3);
acc_t **acc = new acc_t*[H];
@@ -157,7 +156,7 @@ void ffInfo::updateRawImage()
RawImage* temp = new RawImage(*iName);
if( !temp->loadRaw(true)) {
- temp->compress_image(); //\ TODO would be better working on original, because is temporary
+ temp->compress_image(0); //\ TODO would be better working on original, because is temporary
nFiles++;
if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS ) {
@@ -192,12 +191,11 @@ void ffInfo::updateRawImage()
}
} else {
ri = new RawImage(pathname);
-
if( ri->loadRaw(true)) {
delete ri;
ri = nullptr;
} else {
- ri->compress_image();
+ ri->compress_image(0);
}
}
diff --git a/rtengine/green_equil_RT.cc b/rtengine/green_equil_RT.cc
index a9183509d..8b1136359 100644
--- a/rtengine/green_equil_RT.cc
+++ b/rtengine/green_equil_RT.cc
@@ -30,12 +30,11 @@
#include "rt_math.h"
#include "rawimagesource.h"
-
namespace rtengine
{
//void green_equilibrate()//for dcraw implementation
-void RawImageSource::green_equilibrate(float thresh)
+void RawImageSource::green_equilibrate(float thresh, array2D &rawData)
{
// thresh = threshold for performing green equilibration; max percentage difference of G1 vs G2
// G1-G2 differences larger than this will be assumed to be Nyquist texture, and left untouched
@@ -79,7 +78,7 @@ void RawImageSource::green_equilibrate(float thresh)
*/
//now smooth the cfa data
#ifdef _OPENMP
- #pragma omp parallel for
+ #pragma omp parallel for schedule(dynamic,16)
#endif
for (int rr = 4; rr < height - 4; rr++)
@@ -99,8 +98,8 @@ void RawImageSource::green_equilibrate(float thresh)
float d1 = (o1_1 + o1_2 + o1_3 + o1_4) * 0.25f;
float d2 = (o2_1 + o2_2 + o2_3 + o2_4) * 0.25f;
- float c1 = (fabs(o1_1 - o1_2) + fabs(o1_1 - o1_3) + fabs(o1_1 - o1_4) + fabs(o1_2 - o1_3) + fabs(o1_3 - o1_4) + fabs(o1_2 - o1_4)) / 6.0;
- float c2 = (fabs(o2_1 - o2_2) + fabs(o2_1 - o2_3) + fabs(o2_1 - o2_4) + fabs(o2_2 - o2_3) + fabs(o2_3 - o2_4) + fabs(o2_2 - o2_4)) / 6.0;
+ float c1 = (fabs(o1_1 - o1_2) + fabs(o1_1 - o1_3) + fabs(o1_1 - o1_4) + fabs(o1_2 - o1_3) + fabs(o1_3 - o1_4) + fabs(o1_2 - o1_4)) / 6.f;
+ float c2 = (fabs(o2_1 - o2_2) + fabs(o2_1 - o2_3) + fabs(o2_1 - o2_4) + fabs(o2_2 - o2_3) + fabs(o2_3 - o2_4) + fabs(o2_2 - o2_4)) / 6.f;
//%%%%%%%%%%%%%%%%%%%%%%
//vote1=(checker[rr-2][cc]+checker[rr][cc-2]+checker[rr][cc+2]+checker[rr+2][cc]);
@@ -111,10 +110,10 @@ void RawImageSource::green_equilibrate(float thresh)
//pixel interpolation
float gin = cfa[rr][cc];
- float gse = (cfa[rr + 1][cc + 1]) + 0.5 * (cfa[rr][cc] - cfa[rr + 2][cc + 2]);
- float gnw = (cfa[rr - 1][cc - 1]) + 0.5 * (cfa[rr][cc] - cfa[rr - 2][cc - 2]);
- float gne = (cfa[rr - 1][cc + 1]) + 0.5 * (cfa[rr][cc] - cfa[rr - 2][cc + 2]);
- float gsw = (cfa[rr + 1][cc - 1]) + 0.5 * (cfa[rr][cc] - cfa[rr + 2][cc - 2]);
+ float gse = (cfa[rr + 1][cc + 1]) + 0.5f * (cfa[rr][cc] - cfa[rr + 2][cc + 2]);
+ float gnw = (cfa[rr - 1][cc - 1]) + 0.5f * (cfa[rr][cc] - cfa[rr - 2][cc - 2]);
+ float gne = (cfa[rr - 1][cc + 1]) + 0.5f * (cfa[rr][cc] - cfa[rr - 2][cc + 2]);
+ float gsw = (cfa[rr + 1][cc - 1]) + 0.5f * (cfa[rr][cc] - cfa[rr + 2][cc - 2]);
diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h
index 59d46035b..8998fa848 100644
--- a/rtengine/imagesource.h
+++ b/rtengine/imagesource.h
@@ -66,7 +66,7 @@ public:
embProfile(nullptr), idata(nullptr), dirpyrdenoiseExpComp(INFINITY) {}
virtual ~ImageSource () {}
- virtual int load (const Glib::ustring &fname, bool batch = false) = 0;
+ virtual int load (const Glib::ustring &fname, int imageNum = 0, bool batch = false) = 0;
virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true) {};
virtual void demosaic (const RAWParams &raw) {};
virtual void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {};
@@ -80,6 +80,9 @@ public:
virtual bool IsrgbSourceModified() const = 0; // tracks whether cached rgb output of demosaic has been modified
+ virtual void setCurrentFrame(unsigned int frameNum) = 0;
+
+
// use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat*
virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hlp, const ColorManagementParams &cmp, const RAWParams &raw) = 0;
virtual eSensorType getSensorType ()
@@ -157,6 +160,7 @@ public:
{
return this;
}
+ virtual void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) = 0;
};
}
#endif
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index b36a9f9a2..3a8241d95 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -185,6 +185,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
// raw auto CA is bypassed if no high detail is needed, so we have to compute it when high detail is needed
if ( (todo & M_PREPROC) || (!highDetailPreprocessComputed && highDetailNeeded)) {
+ imgsrc->setCurrentFrame(params.raw.bayersensor.imageNum);
imgsrc->preprocess( rp, params.lensProf, params.coarse );
imgsrc->getRAWHistogram( histRedRaw, histGreenRaw, histBlueRaw );
@@ -214,7 +215,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
if (settings->verbose) {
if (imgsrc->getSensorType() == ST_BAYER) {
- printf("Demosaic Bayer image using method: %s\n", rp.bayersensor.method.c_str());
+ printf("Demosaic Bayer image n.%d using method: %s\n", rp.bayersensor.imageNum + 1, rp.bayersensor.method.c_str());
} else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) {
printf("Demosaic X-Trans image with using method: %s\n", rp.xtranssensor.method.c_str());
}
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index f756f347a..30e50bd7d 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -6924,7 +6924,7 @@ double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_si
return 0.0;
}
- Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, w_raw, h_raw, 1, 1.0, FALSE);
+ Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, w_raw, h_raw, 1, 1.0, FALSE, 0);
if (!raw) {
delete thumb;
diff --git a/rtengine/median.h b/rtengine/median.h
index 971452bc3..30adbacb3 100644
--- a/rtengine/median.h
+++ b/rtengine/median.h
@@ -64,6 +64,15 @@ inline vfloat median(std::array array)
}
#endif
+
+template
+inline T median(std::array array)
+{
+ float val1 = std::max(std::min(array[0], array[1]), std::min(array[2], array[3]));
+ float val2 = std::min(std::max(array[0], array[1]), std::max(array[2], array[3]));
+ return (val1 + val2) / 2.f;
+}
+
template
inline T median(std::array array)
{
diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc
new file mode 100644
index 000000000..2e001f686
--- /dev/null
+++ b/rtengine/pixelshift.cc
@@ -0,0 +1,1871 @@
+////////////////////////////////////////////////////////////////
+//
+// pentax pixelshift algorithm with motion detection
+//
+// non adaptive mode is derived from dcrawps (https://github.com/tomtor/dcrawps), but with additional motion correction methods and adapted for RawTherapee data structures
+//
+// If motion correction is enabled only the pixels which are not detected as motion are set
+// That means for a complete image you have to demosaic one of the frames with a bayer demosaicer to fill red, green and blue
+// before calling pixelshift in case motion correction is enabled.
+//
+// copyright (c) Ingo Weyrich 2016
+//
+//
+// pixelshift.cc is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+//
+////////////////////////////////////////////////////////////////
+
+#include
+#include "rawimagesource.h"
+#include "../rtgui/multilangmgr.h"
+#include "procparams.h"
+#include "gauss.h"
+#define BENCHMARK
+#include "StopWatch.h"
+
+namespace
+{
+
+float greenDiff(float a, float b, bool adaptive, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion, int x, int y)
+{
+ // calculate the difference between two green samples
+ if(adaptive) {
+ float gDiff = a - b;
+ gDiff *= eperIso;
+ gDiff *= gDiff;
+ float avg = (a + b) * 0.5f;
+ avg *= eperIso;
+ prnu *= avg;
+ float stddev = stddevFactor * (avg + nreadIso + prnu * prnu);
+
+// if(x >= 4294 && x <= 4303 && y >= 3056 && y <= 3058) {
+// #pragma omp critical
+// std::cout << "x : " << x << " y : " << y << " stddev : " << stddev << " avg : " << avg << " gDiff : " << gDiff << std::endl;
+// }
+
+ float result = gDiff - stddev;
+
+ if(!showMotion) {
+ return result;
+ } else if(result > 0.f) { // for the motion mask
+ return std::fabs(a - b) / (std::max(a, b) + 0.01f);
+ } else {
+ return 0.f;
+ }
+ } else {
+ float gDiff = std::fabs(a - b);
+ // add a small epsilon to avoid division by zero
+ float maxVal = std::max(a, b) + 0.01f;
+ return gDiff / maxVal;
+ }
+}
+
+float nonGreenDiff(float a, float b, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion)
+{
+ // calculate the difference between two nongreen samples
+ float gDiff = a - b;
+ gDiff *= eperIso;
+ gDiff *= gDiff;
+ float avg = (a + b) / 2.f;
+ avg *= eperIso;
+ prnu *= avg;
+ float stddev = stddevFactor * (avg + nreadIso + prnu * prnu);
+ float result = gDiff - stddev;
+
+ if(!showMotion) {
+ return result;
+ } else if(result > 0.f) { // for the motion mask
+ return std::fabs(a - b) / (std::max(a, b) + 0.01f);
+ } else {
+ return 0.f;
+ }
+}
+
+float nonGreenDiffCross(float right, float left, float top, float bottom, float centre, float stddevFactor, float eperIso, float nreadIso, float prnu, bool showMotion)
+{
+ // check non green cross
+ float hDiff = (right + left) * 0.5f - centre;
+ hDiff *= eperIso;
+ hDiff *= hDiff;
+ float vDiff = (top + bottom) * 0.5f - centre;
+ vDiff *= eperIso;
+ vDiff *= vDiff;
+ float avg = ((right + left) + (top + bottom)) * 0.25f;
+ avg *= eperIso;
+ prnu *= avg;
+ float stddev = stddevFactor * (avg + nreadIso + prnu * prnu);
+ float result = std::min(hDiff, vDiff) - stddev;
+
+ if(!showMotion) {
+ return result;
+ } else if(result > 0.f) { // for the motion mask
+ return std::sqrt((result / (stddev + result + 0.01f)));
+ } else {
+ return 0.f;
+ }
+}
+
+void paintMotionMask(int index, bool showMotion, float gridMax, bool showOnlyMask, float *maskDest, float *nonMaskDest0, float *nonMaskDest1)
+{
+ if(showMotion) {
+ if(!showOnlyMask) {
+ // if showMotion is enabled colourize the pixel
+ maskDest[index] = 1000.f + 25000.f * gridMax;
+ nonMaskDest1[index] = nonMaskDest0[index] = 0.f;
+ } else {
+ maskDest[index] = nonMaskDest0[index] = nonMaskDest1[index] = 1000.f + 25000.f * gridMax;
+ }
+ }
+}
+
+void invertMask(int xStart, int xEnd, int yStart, int yEnd, array2D &maskIn, array2D &maskOut)
+{
+ #pragma omp parallel for schedule(dynamic,16)
+
+ for(int i = yStart; i < yEnd; ++i) {
+ #pragma omp simd
+
+ for(int j = xStart; j < xEnd; ++j) {
+ maskOut[i][j] = ~maskIn[i][j];
+ }
+ }
+}
+
+void xorMasks(int xStart, int xEnd, int yStart, int yEnd, array2D &maskIn, array2D &maskOut)
+{
+ #pragma omp parallel for schedule(dynamic,16)
+
+ for(int i = yStart; i < yEnd; ++i) {
+ #pragma omp simd
+
+ for(int j = xStart; j < xEnd; ++j) {
+ maskOut[i][j] ^= maskIn[i][j];
+ }
+ }
+}
+
+void floodFill4Impl(int y, int x, int xStart, int xEnd, int yStart, int yEnd, array2D &mask, std::stack, std::vector>> &coordStack)
+{
+ coordStack.emplace(x, y);
+
+ while(!coordStack.empty()) {
+ auto coord = coordStack.top();
+ coordStack.pop();
+ auto x = coord.first, y = coord.second;
+
+ if (mask[y][x] == 255) {
+ auto yUp = y - 1, yDown = y + 1;
+ bool lastXUp = false, lastXDown = false, firstXUp = false, firstXDown = false;
+ mask[y][x] = 0;
+
+ if(yUp >= yStart && mask[yUp][x] == 255) {
+ coordStack.emplace(x, yUp);
+ firstXUp = lastXUp = true;
+ }
+
+ if(yDown < yEnd && mask[yDown][x] == 255) {
+ coordStack.emplace(x, yDown);
+ firstXDown = lastXDown = true;
+ }
+
+ auto xr = x + 1;
+
+ while(xr < xEnd && mask[y][xr] == 255) {
+ mask[y][xr] = 0;
+
+ if(yUp >= yStart && mask[yUp][xr] == 255) {
+ if(!lastXUp) {
+ coordStack.emplace(xr, yUp);
+ lastXUp = true;
+ }
+ } else {
+ lastXUp = false;
+ }
+
+ if(yDown < yEnd && mask[yDown][xr] == 255) {
+ if(!lastXDown) {
+ coordStack.emplace(xr, yDown);
+ lastXDown = true;
+ }
+ } else {
+ lastXDown = false;
+ }
+
+ xr++;
+ }
+
+ auto xl = x - 1;
+ lastXUp = firstXUp;
+ lastXDown = firstXDown;
+
+ while(xl >= xStart && mask[y][xl] == 255) {
+ mask[y][xl] = 0;
+
+ if(yUp >= yStart && mask[yUp][xl] == 255) {
+ if(!lastXUp) {
+ coordStack.emplace(xl, yUp);
+ lastXUp = true;
+ }
+ } else {
+ lastXUp = false;
+ }
+
+ if(yDown < yEnd && mask[yDown][xl] == 255) {
+ if(!lastXDown) {
+ coordStack.emplace(xl, yDown);
+ lastXDown = true;
+ }
+ } else {
+ lastXDown = false;
+ }
+
+ xl--;
+ }
+
+ mask[y][x] = 0;
+ }
+ }
+}
+
+void floodFill4(int xStart, int xEnd, int yStart, int yEnd, array2D &mask)
+{
+ #pragma omp parallel
+ {
+ std::stack, std::vector>> coordStack;
+
+ #pragma omp for schedule(dynamic,128) nowait
+
+ for(uint16_t i = yStart; i < yEnd; i++)
+ {
+ floodFill4Impl(i, xStart, xStart, xEnd, yStart, yEnd, mask, coordStack);
+ }
+
+ #pragma omp for schedule(dynamic,128) nowait
+
+ for(int16_t i = yEnd - 1; i >= 0 ; i--)
+ {
+ floodFill4Impl(i, xEnd - 1, xStart, xEnd, yStart, yEnd, mask, coordStack);
+ }
+
+ #pragma omp sections nowait
+ {
+ #pragma omp section
+ {
+ uint16_t i = yStart;
+
+ for(uint16_t j = xStart; j < xEnd; j++)
+ {
+ floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack);
+ }
+ }
+ #pragma omp section
+ {
+ uint16_t i = yStart;
+
+ for(uint16_t j = xEnd - 1; j >= xStart; j--)
+ {
+ floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack);
+ }
+ }
+ #pragma omp section
+ {
+ uint16_t i = yEnd;
+
+ for(uint16_t j = xStart; j < xEnd; j++)
+ {
+ floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack);
+ }
+ }
+ #pragma omp section
+ {
+ uint16_t i = yEnd;
+
+ for(uint16_t j = xEnd - 1; j >= xStart; j--)
+ {
+ floodFill4Impl(i, j, xStart, xEnd, yStart, yEnd, mask, coordStack);
+ }
+ }
+ }
+ }
+}
+
+
+}
+
+using namespace std;
+using namespace rtengine;
+#ifdef __OLDPS__
+void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, bool detectMotion, int motion, bool showMotion, bool showOnlyMask, unsigned int frame, RAWParams::BayerSensor::ePSMotionCorrection gridSize_, bool adaptive, float stddevFactorGreen, float stddevFactorRed, float stddevFactorBlue, float eperIso, float nreadIso, float prnu, const std::string &model, float rawWpCorrection, bool checkNonGreenHorizontal, bool checkNonGreenVertical, bool checkNonGreenCross)
+{
+
+ BENCHFUN
+
+ static const float nReadK3II[] = { 3.4f, // ISO 100
+ 3.1f, // ISO 125
+ 2.5f, // ISO 160
+ 2.5f, // ISO 200
+ 2.5f, // ISO 250
+ 2.5f, // ISO 320
+ 2.3f, // ISO 400
+ 2.5f, // ISO 500
+ 2.3f, // ISO 640
+ 2.3f, // ISO 800
+ 2.4f, // ISO 1000
+ 2.3f, // ISO 1250
+ 1.75f, // ISO 1600
+ 1.75f, // ISO 2000
+ 1.75f, // ISO 2500
+ 1.75f, // ISO 3200
+ 1.75f, // ISO 4000
+ 1.75f, // ISO 5000
+ 1.75f, // ISO 6400
+ 1.75f, // ISO 8000
+ 1.75f, // ISO 10000
+ 1.5f, // ISO 12800
+ 1.5f, // ISO 16000
+ 1.5f, // ISO 20000
+ 1.5f, // ISO 25600
+ 1.5f, // ISO 32000
+ 1.5f, // ISO 40000
+ 1.5f, // ISO 51200
+ 1.5f // ISO > 51200 (we get a max ISO value of 65535 from dcraw)
+ };
+
+ static const float ePerIsoK3II = 0.35f;
+
+ static const float nReadK1[] = { 3.45f, // ISO 100
+ 3.15f, // ISO 125
+ 3.45f, // ISO 160
+ 3.0f, // ISO 200
+ 3.0f, // ISO 250
+ 3.0f, // ISO 320
+ 2.7f, // ISO 400
+ 2.7f, // ISO 500
+ 2.7f, // ISO 640
+ 2.5f, // ISO 800
+ 2.5f, // ISO 1000
+ 2.5f, // ISO 1250
+ 2.4f, // ISO 1600
+ 2.4f, // ISO 2000
+ 2.4f, // ISO 2500
+ 2.4f, // ISO 3200
+ 2.4f, // ISO 4000
+ 2.4f, // ISO 5000
+ 2.4f, // ISO 6400
+ 2.4f, // ISO 8000
+ 2.4f, // ISO 10000
+ 2.4f, // ISO 12800
+ 2.4f, // ISO 16000
+ 2.4f, // ISO 20000
+ 2.4f, // ISO 25600
+ 2.4f, // ISO 32000
+ 2.4f, // ISO 40000
+ 2.4f, // ISO 51200
+ 2.4f // ISO > 51200 (we get a max ISO value of 65535 from dcraw)
+ };
+
+ static const float ePerIsoK1 = 0.75f;
+
+ static const float nReadK70[] = { 3.0f, // ISO 100
+ 3.0f, // ISO 125
+ 3.0f, // ISO 160
+ 3.0f, // ISO 200
+ 3.0f, // ISO 250
+ 3.0f, // ISO 320
+ 3.0f, // ISO 400
+ 3.0f, // ISO 500
+ 3.0f, // ISO 640
+ 3.0f, // ISO 800
+ 3.0f, // ISO 1000
+ 3.0f, // ISO 1250
+ 3.0f, // ISO 1600
+ 3.0f, // ISO 2000
+ 3.0f, // ISO 2500
+ 3.0f, // ISO 3200
+ 3.0f, // ISO 4000
+ 3.0f, // ISO 5000
+ 3.0f, // ISO 6400
+ 3.0f, // ISO 8000
+ 3.0f, // ISO 10000
+ 3.0f, // ISO 12800
+ 3.0f, // ISO 16000
+ 3.0f, // ISO 20000
+ 3.0f, // ISO 25600
+ 3.0f, // ISO 32000
+ 3.0f, // ISO 40000
+ 3.0f, // ISO 51200
+ 3.0f // ISO > 51200 (we get a max ISO value of 65535 from dcraw)
+ };
+
+ static const float ePerIsoK70 = 0.5f;
+
+ if (plistener) {
+ plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::pixelshift]));
+ plistener->setProgress(0.0);
+ }
+
+
+ const bool skip = (gridSize_ == RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2);
+ int gridSize = 1;
+
+ switch (gridSize_) {
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid1x1:
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2:
+ gridSize = 1;
+ break;
+
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid3x3:
+ gridSize = 3;
+ break;
+
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid5x5:
+ gridSize = 5;
+ break;
+
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid7x7:
+ gridSize = 7;
+ }
+
+ // Lookup table for non adaptive (slider) mode
+ LUTf log2Lut(32768, LUT_CLIP_BELOW | LUT_CLIP_ABOVE);
+
+ if(detectMotion && !adaptive) {
+ const float lutStrength = 2.f;
+ log2Lut[0] = 0;
+
+ for(int i = 2; i < 65536; i += 2) {
+ log2Lut[i >> 1] = lutStrength * log2(i) / 100.f;
+ }
+ }
+
+ const float scaleGreen = 1.f / scale_mul[1];
+
+ float nRead;
+ float eperIsoModel;
+
+ int nReadIndex = static_cast(round(log2(idata->getISOSpeed() / 100.f) * 3.f));
+
+ if(model.find("K-3") != string::npos) {
+ nRead = nReadK3II[nReadIndex];
+ eperIsoModel = ePerIsoK3II;
+ } else if(model.find("K-1") != string::npos) {
+ nRead = nReadK1[nReadIndex];
+ eperIsoModel = ePerIsoK1;
+ } else {
+ nRead = nReadK70[nReadIndex];
+ eperIsoModel = ePerIsoK70;
+ }
+
+ nRead *= pow(2.f, nreadIso);
+ eperIsoModel *= pow(2.f, eperIso);
+ eperIso = eperIsoModel * (100.f / (rawWpCorrection * idata->getISOSpeed()));
+ float eperIsoGreen = eperIso * scaleGreen;
+
+// printf("Pixelshift parameters : gridSize %d\tadaptive %d\tstdDevFactorGreen %f\telectrons %1.8f\tnread %f\tprnu %1.1f%%\n", gridSize, adaptive, stddevFactorGreen, eperIso, nRead, prnu);
+
+ prnu /= 100.f;
+ stddevFactorGreen *= stddevFactorGreen;
+ stddevFactorRed *= stddevFactorRed;
+ stddevFactorBlue *= stddevFactorBlue;
+
+
+ nRead *= nRead;
+
+ // If the values of two corresponding green pixels differ my more then motionThreshold %, the pixel will be treated as a badGreen pixel
+ float motionThreshold = 1.f - (motion / 100.f);
+ // For shades of green motion indicators
+ const float blendFactor = ((adaptive || motion == 0.f) ? 1.f : 1.f / (1.f - motionThreshold));
+
+ unsigned int offsX = 0, offsY = 0;
+
+ // We have to adjust the offsets for the selected subframe we use for areas with motion
+ switch (frame) {
+ case 0:
+ offsX = offsY = 0;
+ break;
+
+ case 1:
+ offsX = 0;
+ offsY = 1;
+ break;
+
+ case 2:
+ offsX = offsY = 1;
+ break;
+
+ case 3:
+ offsX = 1;
+ offsY = 0;
+ }
+
+ const float thresh = adaptive ? 0.f : motionThreshold;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) {
+ float *greenDest = green[i + offsY];
+ float *nonGreenDest0 = red[i + offsY];
+ float *nonGreenDest1 = blue[i + offsY];
+ int j = winx + border - offsX;
+ int c = FC(i, j);
+ float scaleNonGreen0 = 1.f / scale_mul[0];
+ float scaleNonGreen2 = 1.f / scale_mul[2];
+ float eperIsoNonGreen0 = eperIso / scale_mul[0];
+ float eperIsoNonGreen2 = eperIso / scale_mul[2];
+ float stddevFactorNonGreen0 = stddevFactorRed;
+ float stddevFactorNonGreen2 = stddevFactorBlue;
+ bool blueRow = false;
+
+ if (c == 2 || ((c & 1) && FC(i, j + 1) == 2)) {
+ // row with blue pixels => swap destination pointers for non green pixels
+ blueRow = true;
+ std::swap(nonGreenDest0, nonGreenDest1);
+ std::swap(scaleNonGreen0, scaleNonGreen2);
+ std::swap(eperIsoNonGreen0, eperIsoNonGreen2);
+ std::swap(stddevFactorNonGreen0, stddevFactorNonGreen2);
+ }
+
+ // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop
+ unsigned int offset = (c & 1);
+
+ float greenDifMax[gridSize];
+
+ // green channel motion detection checks the grid around the pixel for differences in green channels
+ if(detectMotion || adaptive) {
+ if(gridSize == 3) {
+ // compute maximum of differences for first two columns of 3x3 grid
+ greenDifMax[0] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset][j - 1], (*rawDataFrames[3 - offset])[i + offset - 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset][j - 1], (*rawDataFrames[2 + offset])[i - offset + 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 2][j - 1], (*rawDataFrames[3 - offset])[i + offset + 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[1] = std::max({greenDiff((*rawDataFrames[0 + offset])[i + offset - 1][j], (*rawDataFrames[2 + offset])[i - offset][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j], (*rawDataFrames[3 - offset])[i + offset][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 1][j], (*rawDataFrames[2 + offset])[i - offset + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ } else if(gridSize == 5) {
+ // compute maximum of differences for first four columns of 5x5 grid
+ greenDifMax[0] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset - 1][j - 2], (*rawDataFrames[3 - offset])[i + offset - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 1][j - 2], (*rawDataFrames[2 + offset])[i - offset][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j - 2], (*rawDataFrames[3 - offset])[i + offset][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 1][j - 2], (*rawDataFrames[2 + offset])[i - offset + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 3][j - 2], (*rawDataFrames[3 - offset])[i + offset + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[1] = std::max({greenDiff((*rawDataFrames[0 + offset])[i + offset - 2][j - 1], (*rawDataFrames[2 + offset])[i - offset - 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset][j - 1], (*rawDataFrames[3 - offset])[i + offset - 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset][j - 1], (*rawDataFrames[2 + offset])[i - offset + 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 2][j - 1], (*rawDataFrames[3 - offset])[i + offset + 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 2][j - 1], (*rawDataFrames[2 + offset])[i - offset + 3][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[2] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset - 1][j], (*rawDataFrames[3 - offset])[i + offset - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 1][j], (*rawDataFrames[2 + offset])[i - offset][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j], (*rawDataFrames[3 - offset])[i + offset][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 1][j], (*rawDataFrames[2 + offset])[i - offset + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 3][j], (*rawDataFrames[3 - offset])[i + offset + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[3] = std::max({greenDiff((*rawDataFrames[0 + offset])[i + offset - 2][j + 1], (*rawDataFrames[2 + offset])[i - offset - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset][j + 1], (*rawDataFrames[3 - offset])[i + offset - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset][j + 1], (*rawDataFrames[2 + offset])[i - offset + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 2][j + 1], (*rawDataFrames[3 - offset])[i + offset + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 2][j + 1], (*rawDataFrames[2 + offset])[i - offset + 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ } else if(gridSize == 7) {
+ // compute maximum of differences for first six columns of 7x7 grid
+ greenDifMax[0] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset - 2][j - 3], (*rawDataFrames[3 - offset])[i + offset - 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 2][j - 3], (*rawDataFrames[2 + offset])[i - offset - 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset][j - 3], (*rawDataFrames[3 - offset])[i + offset - 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset][j - 3], (*rawDataFrames[2 + offset])[i - offset + 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 2][j - 3], (*rawDataFrames[3 - offset])[i + offset + 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 2][j - 3], (*rawDataFrames[2 + offset])[i - offset + 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 4][j - 3], (*rawDataFrames[3 - offset])[i + offset + 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[1] = std::max({greenDiff((*rawDataFrames[0 + offset])[i + offset - 3][j - 2], (*rawDataFrames[2 + offset])[i - offset - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset - 1][j - 2], (*rawDataFrames[3 - offset])[i + offset - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 1][j - 2], (*rawDataFrames[2 + offset])[i - offset][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j - 2], (*rawDataFrames[3 - offset])[i + offset][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 1][j - 2], (*rawDataFrames[2 + offset])[i - offset + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 3][j - 2], (*rawDataFrames[3 - offset])[i + offset + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 3][j - 2], (*rawDataFrames[2 + offset])[i - offset + 4][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[2] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset - 2][j - 1], (*rawDataFrames[3 - offset])[i + offset - 3][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 2][j - 1], (*rawDataFrames[2 + offset])[i - offset - 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset][j - 1], (*rawDataFrames[3 - offset])[i + offset - 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset][j - 1], (*rawDataFrames[2 + offset])[i - offset + 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 2][j - 1], (*rawDataFrames[3 - offset])[i + offset + 1][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 2][j - 1], (*rawDataFrames[2 + offset])[i - offset + 3][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 4][j - 1], (*rawDataFrames[3 - offset])[i + offset + 3][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[3] = std::max({greenDiff((*rawDataFrames[0 + offset])[i + offset - 3][j], (*rawDataFrames[2 + offset])[i - offset - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset - 1][j], (*rawDataFrames[3 - offset])[i + offset - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 1][j], (*rawDataFrames[2 + offset])[i - offset][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j], (*rawDataFrames[3 - offset])[i + offset][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 1][j], (*rawDataFrames[2 + offset])[i - offset + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 3][j], (*rawDataFrames[3 - offset])[i + offset + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 3][j], (*rawDataFrames[2 + offset])[i - offset + 4][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[4] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset - 2][j + 1], (*rawDataFrames[3 - offset])[i + offset - 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 2][j + 1], (*rawDataFrames[2 + offset])[i - offset - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset][j + 1], (*rawDataFrames[3 - offset])[i + offset - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset][j + 1], (*rawDataFrames[2 + offset])[i - offset + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 2][j + 1], (*rawDataFrames[3 - offset])[i + offset + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 2][j + 1], (*rawDataFrames[2 + offset])[i - offset + 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 4][j + 1], (*rawDataFrames[3 - offset])[i + offset + 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[5] = std::max({greenDiff((*rawDataFrames[0 + offset])[i + offset - 3][j + 2], (*rawDataFrames[2 + offset])[i - offset - 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset - 1][j + 2], (*rawDataFrames[3 - offset])[i + offset - 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 1][j + 2], (*rawDataFrames[2 + offset])[i - offset][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j + 2], (*rawDataFrames[3 - offset])[i + offset][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 1][j + 2], (*rawDataFrames[2 + offset])[i - offset + 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 3][j + 2], (*rawDataFrames[3 - offset])[i + offset + 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 3][j + 2], (*rawDataFrames[2 + offset])[i - offset + 4][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ }
+
+ }
+
+ offset ^= 1; // 0 => 1 or 1 => 0
+
+ // this is the index for the last column of the grid. Obviously we have to start with gridSize - 1
+ int lastIndex = gridSize - 1;
+ float korr = 0.f;
+
+ for(; j < winw - (border + offsX); ++j) {
+ offset ^= 1; // 0 => 1 or 1 => 0
+
+ if(detectMotion || adaptive) {
+ bool skipNext = false;
+ float gridMax;
+
+ if(gridSize < 2) {
+ // compute difference for current pixel and skip next pixel, that's the method from dcrawps
+ gridMax = greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j], (*rawDataFrames[3 - offset])[i + offset][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i);
+ skipNext = skip;
+ } else if(gridSize == 3) {
+ // compute maximum of differences for third column of 3x3 grid and save at position lastIndex
+ greenDifMax[lastIndex] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset][j + 1], (*rawDataFrames[3 - offset])[i + offset - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset][j + 1], (*rawDataFrames[2 + offset])[i - offset + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 2][j + 1], (*rawDataFrames[3 - offset])[i + offset + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2]});
+ } else if(gridSize == 5) {
+ // compute maximum of differences for fifth column of 5x5 grid and save at position lastIndex
+ greenDifMax[lastIndex] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset - 1][j + 2], (*rawDataFrames[3 - offset])[i + offset - 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 1][j + 2], (*rawDataFrames[2 + offset])[i - offset][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 1][j + 2], (*rawDataFrames[3 - offset])[i + offset][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 1][j + 2], (*rawDataFrames[2 + offset])[i - offset + 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 3][j + 2], (*rawDataFrames[3 - offset])[i + offset + 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2], greenDifMax[3], greenDifMax[4]});
+ } else if(gridSize == 7) {
+ // compute maximum of differences for 7th column of 7x7 grid and save at position lastIndex
+ greenDifMax[lastIndex] = std::max({greenDiff((*rawDataFrames[1 - offset])[i - offset - 2][j + 3], (*rawDataFrames[3 - offset])[i + offset - 3][j + 4], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset - 2][j + 3], (*rawDataFrames[2 + offset])[i - offset - 1][j + 4], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset][j + 3], (*rawDataFrames[3 - offset])[i + offset - 1][j + 4], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset][j + 3], (*rawDataFrames[2 + offset])[i - offset + 1][j + 4], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 2][j + 3], (*rawDataFrames[3 - offset])[i + offset + 1][j + 4], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[0 + offset])[i + offset + 2][j + 3], (*rawDataFrames[2 + offset])[i - offset + 3][j + 4], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff((*rawDataFrames[1 - offset])[i - offset + 4][j + 3], (*rawDataFrames[3 - offset])[i + offset + 3][j + 4], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2], greenDifMax[3], greenDifMax[4], greenDifMax[5], greenDifMax[6]});
+ }
+
+
+ // adjust index for next column
+ lastIndex ++;
+ lastIndex = lastIndex == gridSize ? 0 : lastIndex;
+
+ // increase motion detection dependent on brightness
+ if(!adaptive) {
+ korr = log2Lut[((int)((*rawDataFrames[1 - offset])[i - offset + 1][j] * scaleGreen)) >> 1];
+ }
+
+ if (gridMax > thresh - korr) {
+ // at least one of the tested pixels of the grid is detected as motion
+ paintMotionMask(j + offsX, showMotion, (gridMax - thresh + korr) * blendFactor, showOnlyMask, greenDest, nonGreenDest0, nonGreenDest1);
+
+ if(skipNext) {
+ // treat the horizontally next pixel also as motion
+ j++;
+ paintMotionMask(j + offsX, showMotion, (gridMax - thresh + korr) * blendFactor, showOnlyMask, greenDest, nonGreenDest0, nonGreenDest1);
+ offset ^= 1;
+ }
+
+ // do not set the motion pixel values. They have already been set by demosaicer or showMotion
+ continue;
+ }
+
+ if(adaptive && checkNonGreenCross) {
+ float ngCentre = (*rawDataFrames[(offset << 1) + offset])[i][j + offset];
+ float ngRight = (*rawDataFrames[((offset ^ 1) << 1) + (offset ^ 1)])[i][j + (offset ^ 1) + 1];
+ float ngLeft = (*rawDataFrames[((offset ^ 1) << 1) + (offset ^ 1)])[i][j + (offset ^ 1) - 1];
+ float diffRight = ngRight - ngCentre;
+ float diffLeft = ngLeft - ngCentre;
+ float diffHorNg0 = -1.f;
+
+ if(diffRight * diffLeft >= 0.f) {
+ float avg = (ngRight + ngLeft) / 2.f;
+ diffHorNg0 = nonGreenDiff(ngCentre, avg, stddevFactorNonGreen0, eperIsoNonGreen0, nRead, prnu, showMotion);
+
+// if(diff > 0.f) {
+// paintMotionMask(j + offsX, showMotion, diff, showOnlyMask, nonGreenDest0, nonGreenDest1, greenDest);
+// continue;
+// }
+ }
+
+ float diffHorNg1 = -1.f;
+ ngCentre = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1];
+ ngRight = (*rawDataFrames[2 - (offset ^ 1)])[i + 1][j - (offset ^ 1) + 2];
+ ngLeft = (*rawDataFrames[2 - (offset ^ 1)])[i + 1][j - (offset ^ 1)];
+ diffRight = ngRight - ngCentre;
+ diffLeft = ngLeft - ngCentre;
+
+ if(diffRight * diffLeft >= 0.f) {
+ float avg = (ngRight + ngLeft) / 2.f;
+ float diffHorNg1 = nonGreenDiff(ngCentre, avg, stddevFactorNonGreen2, eperIsoNonGreen2, nRead, prnu, showMotion);
+
+// if(diff > 0.f) {
+// paintMotionMask(j + offsX, showMotion, diff, showOnlyMask, nonGreenDest1, nonGreenDest0, greenDest);
+// continue;
+// }
+ }
+
+ if( diffHorNg0 * diffHorNg1 < 0.f) {
+ paintMotionMask(j + offsX, showMotion, 1.f, showOnlyMask, nonGreenDest0, nonGreenDest1, greenDest);
+ continue;
+
+ }
+
+// bool motion = false;
+// float ngCentre = (*rawDataFrames[(offset << 1) + offset])[i][j + offset];
+// float ngRight = (*rawDataFrames[((offset ^ 1) << 1) + (offset ^ 1)])[i][j + (offset ^ 1) + 1];
+// float ngLeft = (*rawDataFrames[((offset ^ 1) << 1) + (offset ^ 1)])[i][j + (offset ^ 1) - 1];
+// float ngTop = (*rawDataFrames[((offset << 1) + offset) ^ 1])[i][j + offset];
+// float ngBottom = (*rawDataFrames[((offset << 1) + offset) ^ 1])[i + 2][j + offset];
+// float diff = nonGreenDiffCross(ngRight, ngLeft, ngTop, ngBottom, ngCentre, stddevFactorNonGreen0, eperIsoNonGreen0, nRead, prnu, showMotion);
+//
+// if(diff > 0.f) {
+// motion = true;
+// paintMotionMask(j + offsX, showMotion, diff, showOnlyMask, nonGreenDest0, nonGreenDest1, greenDest);
+// continue;
+// }
+//
+// ngCentre = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1];
+// ngRight = (*rawDataFrames[2 - (offset ^ 1)])[i + 1][j - (offset ^ 1) + 2];
+// ngLeft = (*rawDataFrames[2 - (offset ^ 1)])[i + 1][j - (offset ^ 1)];
+// ngTop = (*rawDataFrames[3 - ((offset << 1) + offset)])[i - 1][j - offset + 1];
+// ngBottom = (*rawDataFrames[3 - ((offset << 1) + offset)])[i + 1][j - offset + 1];
+// diff = nonGreenDiffCross(ngRight, ngLeft, ngTop, ngBottom, ngCentre, stddevFactorNonGreen2, eperIsoNonGreen2, nRead, prnu, showMotion);
+//
+//// if(diff > 0.f) {
+// if((diff > 0.f && !motion) || (diff <= 0.f && motion) ) {
+// paintMotionMask(j + offsX, showMotion, diff, showOnlyMask, nonGreenDest1, nonGreenDest0, greenDest);
+// continue;
+// }
+ }
+
+ if(adaptive && checkNonGreenHorizontal) {
+// float lg = ((*rawDataFrames[1 - (offset^1)])[i - (offset^1) + 1][j - 1] + (*rawDataFrames[3 - (offset^1)])[i + (offset^1)][j]) / 2.f;
+// float cg = ((*rawDataFrames[1 - offset])[i - offset + 1][j] + (*rawDataFrames[3 - offset])[i + offset][j + 1]) / 2.f;
+// float rg = ((*rawDataFrames[1 - (offset^1)])[i - (offset^1) + 1][j + 1] + (*rawDataFrames[3 - (offset^1)])[i + (offset^1)][j + 2]) / 2.f;
+//
+// float lr = (*rawDataFrames[((offset^1) << 1) + (offset^1)])[i][j + (offset^1) - 1];
+// float cr = (*rawDataFrames[(offset << 1) + offset])[i][j + offset];
+// float rr = (*rawDataFrames[((offset^1) << 1) + (offset^1)])[i][j + (offset^1) + 1];
+//
+// float lb = (*rawDataFrames[2 - (offset^1)])[i + 1][j - (offset^1)];
+// float cb = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1];
+// float rb = (*rawDataFrames[2 - (offset^1)])[i + 1][j - (offset^1) + 2];
+//
+// if(blueRow) {
+// std::swap(lr, lb);
+// std::swap(cr, cb);
+// std::swap(rr, rb);
+// }
+//
+// float lh = Color::rgb2h(lr, lg, lb);
+// float ch = Color::rgb2h(cr, cg, cb);
+// float rh = Color::rgb2h(rr, rg, rb);
+//
+// float lHueDiff = lh - ch;
+// float rHueDiff = rh - ch;
+// if(lHueDiff * rHueDiff > 0.f) {
+// if(std::fabs(lHueDiff) > 0.5f && std::fabs(rHueDiff) > 0.5f/* && std::fabs(lHueDiff) < 3.f && std::fabs(rHueDiff) < 3.f*/) {
+// paintMotionMask(j + offsX, showMotion, 1.f, showOnlyMask, nonGreenDest0, nonGreenDest1, greenDest);
+// continue;
+// }
+// }
+ float ngCentre = (*rawDataFrames[(offset << 1) + offset])[i][j + offset];
+ float ngRight = (*rawDataFrames[((offset ^ 1) << 1) + (offset ^ 1)])[i][j + (offset ^ 1) + 1];
+ float ngLeft = (*rawDataFrames[((offset ^ 1) << 1) + (offset ^ 1)])[i][j + (offset ^ 1) - 1];
+ float diffRight = ngRight - ngCentre;
+ float diffLeft = ngLeft - ngCentre;
+
+ if(diffRight * diffLeft >= 0.f) {
+ float avg = (ngRight + ngLeft) / 2.f;
+ float diff = nonGreenDiff(ngCentre, avg, stddevFactorNonGreen0, eperIsoNonGreen0, nRead, prnu, showMotion);
+
+ if(diff > 0.f) {
+ paintMotionMask(j + offsX, showMotion, diff, showOnlyMask, nonGreenDest0, nonGreenDest1, greenDest);
+ continue;
+ }
+ }
+
+ ngCentre = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1];
+ ngRight = (*rawDataFrames[2 - (offset ^ 1)])[i + 1][j - (offset ^ 1) + 2];
+ ngLeft = (*rawDataFrames[2 - (offset ^ 1)])[i + 1][j - (offset ^ 1)];
+ diffRight = ngRight - ngCentre;
+ diffLeft = ngLeft - ngCentre;
+
+ if(diffRight * diffLeft >= 0.f) {
+ float avg = (ngRight + ngLeft) / 2.f;
+ float diff = nonGreenDiff(ngCentre, avg, stddevFactorNonGreen2, eperIsoNonGreen2, nRead, prnu, showMotion);
+
+ if(diff > 0.f) {
+ paintMotionMask(j + offsX, showMotion, diff, showOnlyMask, nonGreenDest1, nonGreenDest0, greenDest);
+ continue;
+ }
+ }
+ }
+
+ if(adaptive && checkNonGreenVertical) {
+ float ngCentre = (*rawDataFrames[(offset << 1) + offset])[i][j + offset];
+ float ngTop = (*rawDataFrames[((offset << 1) + offset) ^ 1])[i][j + offset];
+ float ngBottom = (*rawDataFrames[((offset << 1) + offset) ^ 1])[i + 2][j + offset];
+
+ float diffTop = ngTop - ngCentre;
+ float diffBottom = ngBottom - ngCentre;
+
+ if(diffTop * diffBottom >= 0.f) {
+ float avg = (ngTop + ngBottom) / 2.f;
+ float diff = nonGreenDiff(ngCentre, avg, stddevFactorNonGreen0, eperIsoNonGreen0, nRead, prnu, showMotion);
+
+ if(diff > 0.f) {
+ paintMotionMask(j + offsX, showMotion, diff, showOnlyMask, nonGreenDest0, nonGreenDest1, greenDest);
+ continue;
+ }
+ }
+
+ ngCentre = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1];
+ ngTop = (*rawDataFrames[3 - ((offset << 1) + offset)])[i - 1][j - offset + 1];
+ ngBottom = (*rawDataFrames[3 - ((offset << 1) + offset)])[i + 1][j - offset + 1];
+
+ diffTop = ngTop - ngCentre;
+ diffBottom = ngBottom - ngCentre;
+
+ if(diffTop * diffBottom >= 0.f) {
+ float avg = (ngTop + ngBottom) / 2.f;
+ float diff = nonGreenDiff(ngCentre, avg, stddevFactorNonGreen2, eperIsoNonGreen2, nRead, prnu, showMotion);
+
+ if(diff > 0.f) {
+ paintMotionMask(j + offsX, showMotion, diff, showOnlyMask, nonGreenDest1, nonGreenDest0, greenDest);
+ continue;
+ }
+ }
+ }
+ }
+
+ if(showMotion && showOnlyMask) {
+ greenDest[j + offsX] = nonGreenDest0[j + offsX] = nonGreenDest1[j + offsX] = 0.f;
+ continue;
+ }
+
+ // motion correction disabled or no motion detected => combine the values from the four pixelshift frames
+ greenDest[j + offsX] = ((*rawDataFrames[1 - offset])[i - offset + 1][j] + (*rawDataFrames[3 - offset])[i + offset][j + 1]) / 2.f;
+ nonGreenDest0[j + offsX] = (*rawDataFrames[(offset << 1) + offset])[i][j + offset];
+ nonGreenDest1[j + offsX] = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1];
+ }
+ }
+
+ if(plistener) {
+ plistener->setProgress(1.0);
+ }
+}
+#else
+void RawImageSource::pixelshift(int winx, int winy, int winw, int winh, const RAWParams::BayerSensor &bayerParams, unsigned int frame, const std::string &model, float rawWpCorrection)
+{
+#ifdef PIXELSHIFTDEV
+ BENCHFUN
+#endif
+ const bool detectMotion = bayerParams.pixelShiftMotion > 0;
+ const int motion = bayerParams.pixelShiftMotion;
+ const bool showMotion = bayerParams.pixelshiftShowMotion;
+ const bool showOnlyMask = bayerParams.pixelshiftShowMotionMaskOnly && showMotion;
+ const RAWParams::BayerSensor::ePSMotionCorrection gridSize_ = bayerParams.pixelShiftMotionCorrection;
+ const bool adaptive = bayerParams.pixelShiftAutomatic;
+#ifdef PIXELSHIFTDEV
+ float stddevFactorGreen = bayerParams.pixelShiftStddevFactorGreen;
+ float stddevFactorRed = bayerParams.pixelShiftStddevFactorRed;
+ float stddevFactorBlue = bayerParams.pixelShiftStddevFactorBlue;
+ float nreadIso = bayerParams.pixelShiftNreadIso;
+ float prnu = bayerParams.pixelShiftPrnu;
+ const float redBlueWeight = bayerParams.pixelShiftRedBlueWeight + 1.f;
+#else
+ float stddevFactorGreen = 5.f;
+ float stddevFactorRed = 5.f;
+ float stddevFactorBlue = 5.f;
+ float nreadIso = 0.f;
+ float prnu = 1.f;
+ const float redBlueWeight = 0.7f + 1.f;
+#endif
+ float eperIso = bayerParams.pixelShiftEperIso;
+ const bool checkNonGreenHorizontal = bayerParams.pixelShiftNonGreenHorizontal;
+ const bool checkNonGreenVertical = bayerParams.pixelShiftNonGreenVertical;
+ const bool checkNonGreenCross = bayerParams.pixelShiftNonGreenCross;
+ const bool checkNonGreenAmaze = bayerParams.pixelShiftNonGreenAmaze;
+ const bool checkNonGreenCross2 = bayerParams.pixelShiftNonGreenCross2;
+ const bool checkGreen = bayerParams.pixelShiftGreen;
+ const float greenWeight = 2.f;
+ const bool blurMap = bayerParams.pixelShiftBlur;
+ const float sigma = bayerParams.pixelShiftSigma;
+#ifdef PIXELSHIFTDEV
+ const float threshold = bayerParams.pixelShiftSum + 9.f;
+#else
+ const float threshold = 3.f + 9.f;
+#endif
+ const bool experimental0 = bayerParams.pixelShiftExp0;
+ const bool holeFill = bayerParams.pixelShiftHoleFill;
+ const bool equalBrightness = bayerParams.pixelShiftEqualBright;
+ const bool smoothTransitions = blurMap && bayerParams.pixelShiftSmoothFactor > 0. && !showOnlyMask;
+ const bool automatic = bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Automatic;
+ const float smoothFactor = 1.0 - bayerParams.pixelShiftSmoothFactor;
+
+ static const float nReadK3II[] = { 3.4f, // ISO 100
+ 3.1f, // ISO 125
+ 2.5f, // ISO 160
+ 2.5f, // ISO 200
+ 2.5f, // ISO 250
+ 2.5f, // ISO 320
+ 2.3f, // ISO 400
+ 2.5f, // ISO 500
+ 2.3f, // ISO 640
+ 2.3f, // ISO 800
+ 2.4f, // ISO 1000
+ 2.3f, // ISO 1250
+ 1.75f, // ISO 1600
+ 1.75f, // ISO 2000
+ 1.75f, // ISO 2500
+ 1.75f, // ISO 3200
+ 1.75f, // ISO 4000
+ 1.75f, // ISO 5000
+ 1.75f, // ISO 6400
+ 1.75f, // ISO 8000
+ 1.75f, // ISO 10000
+ 1.5f, // ISO 12800
+ 1.5f, // ISO 16000
+ 1.5f, // ISO 20000
+ 1.5f, // ISO 25600
+ 1.5f, // ISO 32000
+ 1.5f, // ISO 40000
+ 1.5f, // ISO 51200
+ 1.5f // ISO > 51200 (we get a max ISO value of 65535 from dcraw)
+ };
+
+ static const float ePerIsoK3II = 0.35f;
+
+ static const float nReadK1[] = { 3.45f, // ISO 100
+ 3.15f, // ISO 125
+ 3.45f, // ISO 160
+ 3.0f, // ISO 200
+ 3.0f, // ISO 250
+ 3.0f, // ISO 320
+ 2.7f, // ISO 400
+ 2.7f, // ISO 500
+ 2.7f, // ISO 640
+ 2.5f, // ISO 800
+ 2.5f, // ISO 1000
+ 2.5f, // ISO 1250
+ 2.4f, // ISO 1600
+ 2.4f, // ISO 2000
+ 2.4f, // ISO 2500
+ 2.4f, // ISO 3200
+ 2.4f, // ISO 4000
+ 2.4f, // ISO 5000
+ 2.4f, // ISO 6400
+ 2.4f, // ISO 8000
+ 2.4f, // ISO 10000
+ 2.4f, // ISO 12800
+ 2.4f, // ISO 16000
+ 2.4f, // ISO 20000
+ 2.4f, // ISO 25600
+ 2.4f, // ISO 32000
+ 2.4f, // ISO 40000
+ 2.4f, // ISO 51200
+ 2.4f, // ISO 64000
+ 2.4f, // ISO 80000
+ 2.4f, // ISO 102400
+ 2.4f, // ISO 128000
+ 2.4f, // ISO 160000
+ 2.4f // ISO 204800
+ };
+
+ static const float ePerIsoK1 = 0.75f;
+
+ static const float nReadK70[] = { 4.0f, // ISO 100
+ 4.0f, // ISO 125
+ 4.0f, // ISO 160
+ 4.0f, // ISO 200
+ 4.0f, // ISO 250
+ 4.0f, // ISO 320
+ 4.0f, // ISO 400
+ 4.0f, // ISO 500
+ 4.0f, // ISO 640
+ 3.0f, // ISO 800
+ 3.0f, // ISO 1000
+ 3.0f, // ISO 1250
+ 3.0f, // ISO 1600
+ 3.0f, // ISO 2000
+ 3.0f, // ISO 2500
+ 3.0f, // ISO 3200
+ 3.0f, // ISO 4000
+ 3.0f, // ISO 5000
+ 3.0f, // ISO 6400
+ 3.0f, // ISO 8000
+ 3.0f, // ISO 10000
+ 3.0f, // ISO 12800
+ 3.0f, // ISO 16000
+ 3.0f, // ISO 20000
+ 3.0f, // ISO 25600
+ 3.0f, // ISO 32000
+ 3.0f, // ISO 40000
+ 3.0f, // ISO 51200
+ 3.0f // ISO > 51200 (we get a max ISO value of 65535 from dcraw)
+ };
+
+ static const float ePerIsoK70 = 0.5f;
+
+ if (plistener) {
+ plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::pixelshift]));
+ plistener->setProgress(0.0);
+ }
+
+
+ const bool skip = (gridSize_ == RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2);
+ int gridSize = 1;
+ bool nOf3x3 = false;
+
+ switch (gridSize_) {
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid1x1:
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid1x2:
+ gridSize = 1;
+ break;
+
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid3x3:
+ gridSize = 3;
+ break;
+
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid5x5:
+ gridSize = 5;
+ break;
+
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid7x7:
+ gridSize = 7;
+ break;
+
+ case RAWParams::BayerSensor::ePSMotionCorrection::Grid3x3New:
+ gridSize = 1;
+ nOf3x3 = true;
+ }
+
+ if(adaptive && blurMap && nOf3x3 && smoothFactor == 0.f && !showMotion) {
+ if(plistener) {
+ plistener->setProgress(1.0);
+ }
+
+ return;
+ }
+
+
+ // Lookup table for non adaptive (slider) mode
+ LUTf log2Lut(32768, LUT_CLIP_BELOW | LUT_CLIP_ABOVE);
+
+ if(detectMotion && !adaptive) {
+ const float lutStrength = 2.f;
+ log2Lut[0] = 0;
+
+ for(int i = 2; i < 65536; i += 2) {
+ log2Lut[i >> 1] = lutStrength * log2(i) / 100.f;
+ }
+ }
+
+ const float scaleGreen = 1.f / scale_mul[1];
+
+ float nRead;
+ float eperIsoModel;
+
+ int nReadIndex = static_cast(round(log2(idata->getISOSpeed() / 100.f) * 3.f));
+
+ if(model.find("K-3") != string::npos) {
+ nRead = nReadK3II[nReadIndex];
+ eperIsoModel = ePerIsoK3II;
+ } else if(model.find("K-1") != string::npos) {
+ nRead = nReadK1[nReadIndex];
+ eperIsoModel = ePerIsoK1;
+ } else {
+ nRead = nReadK70[nReadIndex];
+ eperIsoModel = ePerIsoK70;
+ }
+
+ nRead *= pow(2.f, nreadIso);
+ eperIsoModel *= pow(2.f, eperIso);
+
+ if(adaptive && experimental0) {
+ eperIso = eperIsoModel * sqrtf(100.f / (rawWpCorrection * idata->getISOSpeed()));
+ } else {
+ eperIso = eperIsoModel * (100.f / (rawWpCorrection * idata->getISOSpeed()));
+ }
+
+#ifdef PIXELSHIFTDEV
+ std::cout << "WL: " << c_white[0] << " BL: " << c_black[0] << " ePerIso multiplicator: " << (65535.f / (c_white[0] - c_black[0])) << std::endl;
+#endif
+ float eperIsoRed = (eperIso / scale_mul[0]) * (65535.f / (c_white[0] - c_black[0]));
+ float eperIsoGreen = (eperIso * scaleGreen) * (65535.f / (c_white[1] - c_black[1]));
+ float eperIsoBlue = (eperIso / scale_mul[2]) * (65535.f / (c_white[2] - c_black[2]));
+
+// printf("Pixelshift parameters : gridSize %d\tadaptive %d\tstdDevFactorGreen %f\telectrons %1.8f\tnread %f\tprnu %1.1f%%\n", gridSize, adaptive, stddevFactorGreen, eperIso, nRead, prnu);
+
+ prnu /= 100.f;
+ stddevFactorGreen *= stddevFactorGreen;
+ stddevFactorRed *= stddevFactorRed;
+ stddevFactorBlue *= stddevFactorBlue;
+
+
+ nRead *= nRead;
+
+ // If the values of two corresponding green pixels differ my more then motionThreshold %, the pixel will be treated as a badGreen pixel
+ float motionThreshold = 1.f - (motion / 100.f);
+ // For shades of green motion indicators
+ const float blendFactor = ((adaptive || motion == 0.f) ? 1.f : 1.f / (1.f - motionThreshold));
+
+ unsigned int offsX = 0, offsY = 0;
+
+ if(!bayerParams.pixelShiftMedian || !adaptive) {
+ // We have to adjust the offsets for the selected subframe we use for areas with motion
+ switch (frame) {
+ case 0:
+ offsX = offsY = 0;
+ break;
+
+ case 1:
+ offsX = 0;
+ offsY = 1;
+ break;
+
+ case 2:
+ offsX = offsY = 1;
+ break;
+
+ case 3:
+ offsX = 1;
+ offsY = 0;
+ }
+ }
+
+ const float thresh = adaptive ? 0.f : motionThreshold;
+ array2D psRed(winw + 32, winh); // increase width to avoid cache conflicts
+ array2D psG1(winw + 32, winh);
+ array2D psG2(winw + 32, winh);
+ array2D psBlue(winw + 32, winh);
+
+// calculate average green brightness for each frame
+ double greenBrightness[4] = {};
+
+ if(equalBrightness) {
+ LUT *histo[4];
+
+ for(int i = 0; i < 4; ++i) {
+ histo[i] = new LUT(65536);
+ histo[i]->clear();
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ LUT *histoThr[4];
+
+ for(int i = 0; i < 4; ++i) {
+ histoThr[i] = new LUT(65536);
+ histoThr[i]->clear();
+ }
+
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16)
+#endif
+
+ for(int i = winy + 1; i < winh - 1; ++i) {
+ int j = winx + 1;
+ int c = FC(i, j);
+
+ // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop
+ unsigned int offset = (c & 1);
+ offset ^= 1; // 0 => 1 or 1 => 0
+
+ for(; j < winw - 1; ++j) {
+ offset ^= 1; // 0 => 1 or 1 => 0
+
+ // store the values from the 4 frames into 4 different temporary planes
+ float green1 = (*rawDataFrames[1 - offset])[i - offset + 1][j];
+ float green2 = (*rawDataFrames[3 - offset])[i + offset][j + 1];
+ (*histoThr[1 - offset])[green1]++;
+ (*histoThr[3 - offset])[green2]++;
+ }
+ }
+
+ #pragma omp critical
+ {
+ for(int i = 0; i < 4; ++i) {
+ (*histo[i]) += (*histoThr[i]);
+ delete histoThr[i];
+ }
+ }
+ }
+
+ float medians[4];
+
+ for(int i = 0; i < 4; ++i) {
+ //find median of histogram
+ uint32_t median = 0, count = 0;
+ uint32_t datalen = (winh - 2) * (winw - 2) / 2;
+
+ while (count < datalen / 2) {
+ count += (*histo[i])[median];
+ ++median;
+ }
+
+ medians[i] = (median + median - 1) / 2.f;
+ delete histo[i];
+ }
+
+ const float medianMaster = medians[frame];
+
+ for(int i = 0; i < 4; ++i) {
+ greenBrightness[i] = medianMaster / medians[i];
+ }
+
+#ifdef PIXELSHIFTDEV
+ std::cout << "brightness factors by median : " << greenBrightness[0] << " " << greenBrightness[1] << " " << greenBrightness[2] << " " << greenBrightness[3] << std::endl;
+#endif
+
+ } else {
+ greenBrightness[0] = greenBrightness[1] = greenBrightness[2] = greenBrightness[3] = 1.f;
+ }
+
+// fill channels psRed, psG1, psG2 and psBlue
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for(int i = winy + 1; i < winh - 1; ++i) {
+ float *greenDest1 = psG1[i];
+ float *greenDest2 = psG2[i];
+ float *nonGreenDest0 = psRed[i];
+ float *nonGreenDest1 = psBlue[i];
+ int j = winx + 1;
+ int c = FC(i, j);
+
+ if (c == 2 || ((c & 1) && FC(i, j + 1) == 2)) {
+ // row with blue pixels => swap destination pointers for non green pixels
+ std::swap(nonGreenDest0, nonGreenDest1);
+ std::swap(greenDest1, greenDest2);
+ }
+
+ // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop
+ unsigned int offset = (c & 1);
+ offset ^= 1; // 0 => 1 or 1 => 0
+
+ for(; j < winw - 1; ++j) {
+ offset ^= 1; // 0 => 1 or 1 => 0
+
+ // store the values from the 4 frames into 4 different temporary planes
+ greenDest1[j] = (*rawDataFrames[1 - offset])[i - offset + 1][j] * greenBrightness[1 - offset];
+ greenDest2[j] = (*rawDataFrames[3 - offset])[i + offset][j + 1] * greenBrightness[3 - offset];
+ nonGreenDest0[j] = (*rawDataFrames[(offset << 1) + offset])[i][j + offset] * greenBrightness[(offset << 1) + offset];
+ nonGreenDest1[j] = (*rawDataFrames[2 - offset])[i + 1][j - offset + 1] * greenBrightness[2 - offset];
+ }
+ }
+
+// now that the temporary planes are filled for easy access we do the motion detection
+#ifdef PIXELSHIFTDEV
+ int sum[2] = {0};
+#endif
+ float pixelcount = ((winh - (border + offsY) - (winy + border - offsY)) * (winw - (border + offsX) - (winx + border - offsX))) / 2.f;
+
+ array2D psMask(winw, winh);
+
+
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+#ifdef PIXELSHIFTDEV
+ int sumThr[2] = {0};
+#endif
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic,16) nowait
+#endif
+
+ for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) {
+ float *greenDest = green[i + offsY];
+ float *redDest = red[i + offsY];
+ float *blueDest = blue[i + offsY];
+ int j = winx + border - offsX;
+
+ float greenDifMax[gridSize]; // Here we store the maximum differences per Column
+
+
+ // green channel motion detection checks the grid around the pixel for differences in green channels
+#ifdef PIXELSHIFTDEV
+
+ if(detectMotion || (adaptive && checkGreen)) {
+ if(gridSize == 3) {
+ // compute maximum of differences for first two columns of 3x3 grid
+ greenDifMax[0] = std::max({greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[1] = std::max({greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ } else if(gridSize == 5) {
+ // compute maximum of differences for first four columns of 5x5 grid
+ greenDifMax[0] = std::max({greenDiff(psG1[i - 2][j - 2], psG2[i - 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j - 2], psG2[i - 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j - 2], psG2[ i ][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j - 2], psG2[i + 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j - 2], psG2[i + 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[1] = std::max({greenDiff(psG1[i - 2][j - 1], psG2[i - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j - 1], psG2[i + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[2] = std::max({greenDiff(psG1[i - 2][ j ], psG2[i - 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][ j ], psG2[i + 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[3] = std::max({greenDiff(psG1[i - 2][j + 1], psG2[i - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j + 1], psG2[i + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ } else if(gridSize == 7) {
+ // compute maximum of differences for first six columns of 7x7 grid
+ greenDifMax[0] = std::max({greenDiff(psG1[i - 3][j - 3], psG2[i - 3][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 2][j - 3], psG2[i - 2][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j - 3], psG2[i - 1][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j - 3], psG2[ i ][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j - 3], psG2[i + 1][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j - 3], psG2[i + 2][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 3][j - 3], psG2[i + 3][j - 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[1] = std::max({greenDiff(psG1[i - 3][j - 2], psG2[i - 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 2][j - 2], psG2[i - 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j - 2], psG2[i - 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j - 2], psG2[ i ][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j - 2], psG2[i + 1][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j - 2], psG2[i + 2][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 3][j - 2], psG2[i + 3][j - 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[2] = std::max({greenDiff(psG1[i - 3][j - 1], psG2[i - 3][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 2][j - 1], psG2[i - 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j - 1], psG2[i - 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j - 1], psG2[ i ][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j - 1], psG2[i + 1][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j - 1], psG2[i + 2][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 3][j - 1], psG2[i + 3][j - 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[3] = std::max({greenDiff(psG1[i - 3][ j ], psG2[i - 3][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 2][ j ], psG2[i - 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][ j ], psG2[i - 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][ j ], psG2[ i ][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][ j ], psG2[i + 1][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][ j ], psG2[i + 2][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 3][ j ], psG2[i + 3][ j ], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[4] = std::max({greenDiff(psG1[i - 3][j + 1], psG2[i - 3][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 2][j + 1], psG2[i - 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j + 1], psG2[i + 2][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 3][j + 1], psG2[i + 3][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ greenDifMax[5] = std::max({greenDiff(psG1[i - 3][j + 2], psG2[i - 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 2][j + 2], psG2[i - 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j + 2], psG2[i - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j + 2], psG2[ i ][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j + 2], psG2[i + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j + 2], psG2[i + 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 3][j + 2], psG2[i + 3][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ }
+
+ }
+
+#endif
+
+ // this is the index for the last column of the grid. Obviously we have to start with gridSize - 1
+ int lastIndex = gridSize - 1;
+ float korr = 0.f;
+ int c = FC(i, j);
+ bool blueRow = false;
+
+ if (c == 2 || ((c & 1) && FC(i, j + 1) == 2)) {
+ // row with blue pixels => swap destination pointers for non green pixels
+ blueRow = true;
+ }
+
+ // offset to keep the code short. It changes its value between 0 and 1 for each iteration of the loop
+ unsigned int offset = (c & 1);
+
+ for(; j < winw - (border + offsX); ++j) {
+ psMask[i][j] = 1.f;
+
+ offset ^= 1; // 0 => 1 or 1 => 0
+
+ if(detectMotion || (adaptive && checkGreen)) {
+ bool skipNext = false;
+ float gridMax;
+
+#ifdef PIXELSHIFTDEV
+
+ if(gridSize < 2) {
+ // compute difference for current pixel and skip next pixel, that's roughly the method from dcrawps
+#endif
+ gridMax = greenDiff(psG1[i][j], psG2[i][j], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i);
+#ifdef PIXELSHIFTDEV
+
+ skipNext = skip;
+ } else if(gridSize == 3) {
+ // compute maximum of differences for third column of 3x3 grid and save at position lastIndex
+ greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 1][j + 1], psG2[i - 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j + 1], psG2[ i ][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j + 1], psG2[i + 1][j + 1], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ // calculate maximum of whole grid by calculating maximum of grid column max values
+ gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2]});
+ // adjust index for next column
+ lastIndex ++;
+ lastIndex = lastIndex == gridSize ? 0 : lastIndex;
+ } else if(gridSize == 5) {
+ // compute maximum of differences for fifth column of 5x5 grid and save at position lastIndex
+ greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 2][j + 2], psG2[i - 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j + 2], psG2[i - 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j + 2], psG2[ i ][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j + 2], psG2[i + 1][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j + 2], psG2[i + 2][j + 2], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i)
+ });
+ // calculate maximum of whole grid by calculating maximum of grid column max values
+ gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2], greenDifMax[3], greenDifMax[4]});
+ // adjust index for next column
+ lastIndex ++;
+ lastIndex = lastIndex == gridSize ? 0 : lastIndex;
+ } else if(gridSize == 7) {
+ // compute maximum of differences for 7th column of 7x7 grid and save at position lastIndex
+ greenDifMax[lastIndex] = std::max({greenDiff(psG1[i - 3][j + 3], psG2[i - 3][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 2][j + 3], psG2[i - 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i - 1][j + 3], psG2[i - 1][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[ i ][j + 3], psG2[ i ][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 1][j + 3], psG2[i + 1][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 2][j + 3], psG2[i + 2][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ greenDiff(psG1[i + 3][j + 3], psG2[i + 3][j + 3], adaptive, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion, j, i),
+ });
+ // calculate maximum of whole grid by calculating maximum of grid column max values
+ gridMax = std::max({greenDifMax[0], greenDifMax[1], greenDifMax[2], greenDifMax[3], greenDifMax[4], greenDifMax[5], greenDifMax[6]});
+ // adjust index for next column
+ lastIndex ++;
+ lastIndex = lastIndex == gridSize ? 0 : lastIndex;
+ }
+
+ if(!adaptive) {
+ // increase motion detection dependent on brightness
+ korr = log2Lut[((int)(psG1[i][j] * scaleGreen)) >> 1];
+ }
+
+#endif
+
+ if (gridMax > thresh - korr) {
+#ifdef PIXELSHIFTDEV
+ sumThr[offset] ++;
+
+ if(nOf3x3) {
+#endif
+ psMask[i][j] = greenWeight;
+#ifdef PIXELSHIFTDEV
+ }
+
+ else if((offset == (frame & 1)) && checkNonGreenVertical) {
+ if(frame > 1) {
+ green[i + offsY][j + offsX] = blueRow ? psG1[i][j] : psG2[i][j];
+ } else {
+ green[i + offsY][j + offsX] = blueRow ? psG2[i][j] : psG1[i][j];;
+ }
+
+ } else {
+ // at least one of the tested green pixels of the grid is detected as motion
+ paintMotionMask(j + offsX, showMotion, (gridMax - thresh + korr) * blendFactor, showOnlyMask, greenDest, redDest, blueDest);
+
+ if(skipNext) {
+ // treat the horizontally next pixel also as motion
+ j++;
+ paintMotionMask(j + offsX, showMotion, (gridMax - thresh + korr) * blendFactor, showOnlyMask, greenDest, redDest, blueDest);
+ }
+ }
+
+#endif
+ // do not set the motion pixel values. They have already been set by demosaicer or showMotion
+ continue;
+ }
+ }
+
+ if(adaptive) {
+ if(checkNonGreenCross) {
+ // check red cross
+ float redTop = psRed[i - 1][ j ];
+ float redLeft = psRed[ i ][j - 1];
+ float redCentre = psRed[ i ][ j ];
+ float redRight = psRed[ i ][j + 1];
+ float redBottom = psRed[i + 1][ j ];
+ float redDiff = nonGreenDiffCross(redRight, redLeft, redTop, redBottom, redCentre, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion);
+
+ if(redDiff > 0.f) {
+#ifdef PIXELSHIFTDEV
+
+ if(nOf3x3) {
+#endif
+ psMask[i][j] = redBlueWeight;
+#ifdef PIXELSHIFTDEV
+ } else {
+ paintMotionMask(j + offsX, showMotion, redDiff, showOnlyMask, redDest, blueDest, greenDest);
+ }
+
+#endif
+ continue;
+ }
+
+ // check blue cross
+ float blueTop = psBlue[i - 1][ j ];
+ float blueLeft = psBlue[ i ][j - 1];
+ float blueCentre = psBlue[ i ][ j ];
+ float blueRight = psBlue[ i ][j + 1];
+ float blueBottom = psBlue[i + 1][ j ];
+ float blueDiff = nonGreenDiffCross(blueRight, blueLeft, blueTop, blueBottom, blueCentre, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion);
+
+ if(blueDiff > 0.f) {
+#ifdef PIXELSHIFTDEV
+
+ if(nOf3x3) {
+#endif
+ psMask[i][j] = redBlueWeight;
+#ifdef PIXELSHIFTDEV
+ } else {
+ paintMotionMask(j + offsX, showMotion, blueDiff, showOnlyMask, blueDest, redDest, greenDest);
+ }
+
+#endif
+ continue;
+
+ }
+ }
+
+#ifdef PIXELSHIFTDEV
+
+ if(checkNonGreenHorizontal) {
+ float redLeft = psRed[ i ][j - 1];
+ float redCentre = psRed[ i ][ j ];
+ float redRight = psRed[ i ][j + 1];
+
+ float redDiffLeft = redLeft - redCentre;
+ float redDiffRight = redRight - redCentre;
+
+ if(redDiffLeft * redDiffRight >= 0.f) {
+ float redAvg = (redRight + redLeft) / 2.f;
+ float redDiffHor = nonGreenDiff(redCentre, redAvg, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion);
+
+ if(redDiffHor > 0.f) {
+ if(nOf3x3) {
+ psMask[i][j] = redBlueWeight;
+ } else {
+ paintMotionMask(j + offsX, showMotion, redDiffHor, showOnlyMask, redDest, blueDest, greenDest);
+ }
+
+ continue;
+ }
+ }
+
+ float blueLeft = psBlue[ i ][j - 1];
+ float blueCentre = psBlue[ i ][ j ];
+ float blueRight = psBlue[ i ][j + 1];
+
+ float blueDiffLeft = blueLeft - blueCentre;
+ float blueDiffRight = blueRight - blueCentre;
+
+ if(blueDiffLeft * blueDiffRight >= 0.f) {
+ float blueAvg = (blueRight + blueLeft) / 2.f;
+ float blueDiffHor = nonGreenDiff(blueCentre, blueAvg, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion);
+
+ if(blueDiffHor > 0.f) {
+ if(nOf3x3) {
+ psMask[i][j] = redBlueWeight;
+ } else {
+ paintMotionMask(j + offsX, showMotion, blueDiffHor, showOnlyMask, blueDest, redDest, greenDest);
+ }
+
+ continue;
+ }
+ }
+ }
+
+ if(checkNonGreenVertical) {
+ // check red vertically
+ float redTop = psRed[i - 1][ j ];
+ float redCentre = psRed[ i ][ j ];
+ float redBottom = psRed[i + 1][ j ];
+
+ float redDiffTop = redTop - redCentre;
+ float redDiffBottom = redBottom - redCentre;
+
+ if(redDiffTop * redDiffBottom >= 0.f) {
+ float redAvg = (redTop + redBottom) / 2.f;
+ float redDiff = nonGreenDiff(redCentre, redAvg, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion);
+
+ if(redDiff > 0.f) {
+ if(nOf3x3) {
+ psMask[i][j] = redBlueWeight;
+ } else {
+ paintMotionMask(j + offsX, showMotion, redDiff, showOnlyMask, redDest, blueDest, greenDest);
+ }
+
+ continue;
+ }
+ }
+
+ // check blue vertically
+ float blueTop = psBlue[i - 1][ j ];
+ float blueCentre = psBlue[ i ][ j ];
+ float blueBottom = psBlue[i + 1][ j ];
+
+ float blueDiffTop = blueTop - blueCentre;
+ float blueDiffBottom = blueBottom - blueCentre;
+
+ if(blueDiffTop * blueDiffBottom >= 0.f) {
+ float blueAvg = (blueTop + blueBottom) / 2.f;
+ float blueDiff = nonGreenDiff(blueCentre, blueAvg, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion);
+
+ if(blueDiff > 0.f) {
+ if(nOf3x3) {
+ psMask[i][j] = redBlueWeight;
+ } else {
+ paintMotionMask(j + offsX, showMotion, blueDiff, showOnlyMask, blueDest, redDest, greenDest);
+ }
+
+ continue;
+ }
+ }
+ }
+
+ if(checkNonGreenAmaze) {
+ // check current pixel against amaze
+ float redCentre = psRed[ i ][ j ];
+ float redAmaze = red[i + offsY][j + offsX];
+
+ float redDiffAmaze = nonGreenDiff(redCentre, redAmaze, stddevFactorRed, eperIsoRed, nRead, prnu, showMotion);
+
+ if(redDiffAmaze > 0.f) {
+ if(nOf3x3) {
+ psMask[i][j] = redBlueWeight;
+ } else {
+ paintMotionMask(j + offsX, showMotion, redDiffAmaze, showOnlyMask, redDest, blueDest, greenDest);
+ }
+
+ continue;
+ }
+
+ float blueCentre = psBlue[ i ][ j ];
+ float blueAmaze = blue[i + offsY][j + offsX];
+
+ float blueDiffAmaze = nonGreenDiff(blueCentre, blueAmaze, stddevFactorBlue, eperIsoBlue, nRead, prnu, showMotion);
+
+ if(blueDiffAmaze > 0.f) {
+ if(nOf3x3) {
+ psMask[i][j] = redBlueWeight;
+ } else {
+ paintMotionMask(j + offsX, showMotion, blueDiffAmaze, showOnlyMask, blueDest, redDest, greenDest);
+ }
+
+ continue;
+ }
+ }
+
+ if(checkNonGreenCross2) { // for green amaze
+ float greenCentre = (psG1[ i ][ j ] + psG2[ i ][ j ]) / 2.f;
+ float greenAmaze = green[i + offsY][j + offsX];
+ float greenDiffAmaze = nonGreenDiff(greenCentre, greenAmaze, stddevFactorGreen, eperIsoGreen, nRead, prnu, showMotion);
+
+ if(greenDiffAmaze > 0.f) {
+ if(nOf3x3) {
+ psMask[i][j] = greenWeight;
+ } else {
+ paintMotionMask(j + offsX, showMotion, greenDiffAmaze, showOnlyMask, greenDest, redDest, blueDest);
+ }
+
+ continue;
+ }
+ }
+
+ if(experimental0) { // for experiments
+
+ }
+
+#endif
+ }
+
+ if(showOnlyMask) { // we want only motion mask => paint areas without motion in pure black
+ red[i + offsY][j + offsX] = green[i + offsY][j + offsX] = blue[i + offsY][j + offsX] = 0.f;
+ } else if(!(adaptive && nOf3x3)) {
+ // no motion detected, replace the a priori demosaiced values by the pixelshift combined values
+ red[i + offsY][j + offsX] = psRed[i][j];
+ green[i + offsY][j + offsX] = (psG1[i][j] + psG2[i][j]) / 2.f;
+ blue[i + offsY][j + offsX] = psBlue[i][j];
+ }
+ }
+ }
+
+#ifdef PIXELSHIFTDEV
+
+#ifdef _OPENMP
+ #pragma omp critical
+#endif
+ {
+ sum[0] += sumThr[0];
+ sum[1] += sumThr[0];
+ }
+#endif
+ }
+
+
+#ifdef PIXELSHIFTDEV
+ float percent0 = 100.f * sum[0] / pixelcount;
+ float percent1 = 100.f * sum[1] / pixelcount;
+
+ std::cout << fileName << " : Green detections at stddev " << std::setprecision( 2 ) << bayerParams.pixelShiftStddevFactorGreen << " : Frame 1/3 : " << std::setprecision( 6 ) << sum[0] << " (" << percent0 << "%)" << " Frame 2/4 : " << sum[1] << " (" << percent1 << "%)" << std::endl;
+#endif
+
+ if(adaptive && nOf3x3) {
+ if(blurMap) {
+ #pragma omp parallel
+ {
+ gaussianBlur(psMask, psMask, winw, winh, sigma);
+ }
+ }
+
+ array2D mask(W, H, ARRAY2D_CLEAR_DATA);
+ array2D maskInv(W, H, ARRAY2D_CLEAR_DATA);
+
+ #pragma omp parallel for schedule(dynamic,16)
+
+ for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) {
+ int j = winx + border - offsX;
+ float v3sum[3] = {0.f};
+
+ for(int v = -1; v <= 1; v++) {
+ for(int h = -1; h < 1; h++) {
+ v3sum[1 + h] += (psMask[i + v][j + h]);
+ }
+ }
+
+ float blocksum = v3sum[0] + v3sum[1];
+
+ for(int voffset = 2; j < winw - (border + offsX); ++j, ++voffset) {
+ float colSum = psMask[i - 1][j + 1] + psMask[i][j + 1] + psMask[i + 1][j + 1];
+ voffset = voffset == 3 ? 0 : voffset; // faster than voffset %= 3;
+ blocksum -= v3sum[voffset];
+ blocksum += colSum;
+ v3sum[voffset] = colSum;
+
+ if(blocksum >= threshold) {
+ mask[i][j] = 255;
+ }
+ }
+ }
+
+ if(holeFill) {
+ invertMask(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), mask, maskInv);
+ floodFill4(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), maskInv);
+ xorMasks(winx + border - offsX, winw - (border + offsX), winy + border - offsY, winh - (border + offsY), maskInv, mask);
+ }
+
+
+ #pragma omp parallel for schedule(dynamic,16)
+
+ for(int i = winy + border - offsY; i < winh - (border + offsY); ++i) {
+#ifdef __SSE2__
+
+ if(smoothTransitions) {
+ vfloat onev = F2V(1.f);
+ vfloat smoothv = F2V(smoothFactor);
+ int j = winx + border - offsX;
+
+ for(; j < winw - (border + offsX) - 3; j += 4) {
+ vfloat blendv = vmaxf(LVFU(psMask[i][j]), onev) - onev;
+ 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] - 1.f, 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) {
+ paintMotionMask(j + offsX, showMotion, 0.5f, showOnlyMask, greenDest, redDest, blueDest);
+ } else if(showOnlyMask) { // we want only motion mask => paint areas without motion in pure black
+ red[i + offsY][j + offsX] = green[i + offsY][j + offsX] = blue[i + offsY][j + offsX] = 0.f;
+ } else {
+ if(smoothTransitions) {
+#ifdef __SSE2__
+ float blend = psMask[i][j];
+#else
+ float blend = pow_F(std::max(psMask[i][j] - 1.f, 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]) * 0.5f);
+ 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]) * 0.5f;
+ blue[i + offsY][j + offsX] = psBlue[i][j];
+ }
+ }
+ }
+ }
+ }
+
+ if(plistener) {
+ plistener->setProgress(1.0);
+ }
+}
+#endif
\ No newline at end of file
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index bca679bdb..a1c6f58f9 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -471,6 +471,36 @@ enum ProcEvent {
EvLskal = 441,
EvOBPCompens = 442,
EvWBtempBias = 443,
+ EvRawImageNum = 444,
+ EvPixelShiftMotion = 445,
+ EvPixelShiftMotionCorrection = 446,
+ EvPixelShiftStddevFactorGreen = 447,
+ EvPixelShiftEperIso = 448,
+ EvPixelShiftNreadIso = 449,
+ EvPixelShiftPrnu = 450,
+ EvPixelshiftShowMotion = 451,
+ EvPixelshiftShowMotionMaskOnly = 452,
+ EvPixelShiftAutomatic = 453,
+ EvPixelShiftNonGreenHorizontal = 454,
+ EvPixelShiftNonGreenVertical = 455,
+ EvPixelShiftNonGreenCross = 456,
+ EvPixelShiftStddevFactorRed = 457,
+ EvPixelShiftStddevFactorBlue = 458,
+ EvPixelShiftGreenAmaze = 459,
+ EvPixelShiftNonGreenAmaze = 460,
+ EvPixelShiftGreen = 461,
+ EvPixelShiftRedBlueWeight = 462,
+ EvPixelShiftBlur = 463,
+ EvPixelShiftSigma = 464,
+ EvPixelShiftSum = 465,
+ EvPixelShiftExp0 = 466,
+ EvPixelShiftHoleFill = 467,
+ EvPixelShiftMedian = 468,
+ EvPixelShiftMedian3 = 469,
+ EvPixelShiftMotionMethod = 470,
+ EvPixelShiftSmooth = 471,
+ EvPixelShiftLmmse = 472,
+ EvPixelShiftEqualBright = 473,
NUMOFEVENTS
};
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index f01fa57d2..9da09998d 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -40,7 +40,7 @@ const int br = (int) options.rtSettings.bot_right;
const int tl = (int) options.rtSettings.top_left;
const int bl = (int) options.rtSettings.bot_left;
-const char *RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::numMethods] = {"amaze", "igv", "lmmse", "eahd", "hphd", "vng4", "dcb", "ahd", "fast", "mono", "none" };
+const char *RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::numMethods] = {"amaze", "igv", "lmmse", "eahd", "hphd", "vng4", "dcb", "ahd", "fast", "mono", "none", "pixelshift" };
const char *RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::numMethods] = {"3-pass (best)", "1-pass (medium)", "fast", "mono", "none" };
const char *RAWParams::ff_BlurTypestring[RAWParams::numFlatFileBlurTypes] = {/*"Parametric",*/ "Area Flatfield", "Vertical Flatfield", "Horizontal Flatfield", "V+H Flatfield"};
@@ -875,10 +875,41 @@ void CoarseTransformParams::setDefaults()
hflip = false;
vflip = false;
}
+void RAWParams::BayerSensor::setPixelShiftDefaults()
+{
+ pixelShiftMotion = 0;
+ pixelShiftMotionCorrection = RAWParams::BayerSensor::Grid3x3New;
+ pixelShiftMotionCorrectionMethod = RAWParams::BayerSensor::Automatic;
+ pixelShiftStddevFactorGreen = 5.0;
+ pixelShiftStddevFactorRed = 5.0;
+ pixelShiftStddevFactorBlue = 5.0;
+ pixelShiftEperIso = 0.0;
+ pixelShiftNreadIso = 0.0;
+ pixelShiftPrnu = 1.0;
+ pixelShiftSigma = 1.0;
+ pixelShiftSum = 3.0;
+ pixelShiftRedBlueWeight = 0.7;
+ pixelShiftAutomatic = true;
+ pixelShiftNonGreenHorizontal = false;
+ pixelShiftNonGreenVertical = false;
+ pixelShiftHoleFill = true;
+ pixelShiftMedian = false;
+ pixelShiftMedian3 = false;
+ pixelShiftGreen = true;
+ pixelShiftBlur = true;
+ pixelShiftSmoothFactor = 0.7;
+ pixelShiftExp0 = false;
+ pixelShiftLmmse = false;
+ pixelShiftEqualBright = false;
+ pixelShiftNonGreenCross = true;
+ pixelShiftNonGreenCross2 = false;
+ pixelShiftNonGreenAmaze = false;
+}
void RAWParams::setDefaults()
{
bayersensor.method = RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze];
+ bayersensor.imageNum = 0;
bayersensor.ccSteps = 0;
bayersensor.dcb_iterations = 2;
bayersensor.dcb_enhance = true;
@@ -913,6 +944,10 @@ void RAWParams::setDefaults()
hotPixelFilter = false;
deadPixelFilter = false;
hotdeadpix_thresh = 100;
+ bayersensor.setPixelShiftDefaults();
+ bayersensor.pixelshiftShowMotion = false;
+ bayersensor.pixelshiftShowMotionMaskOnly = false;
+
}
void ColorManagementParams::setDefaults()
@@ -3320,6 +3355,10 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b
keyFile.set_string ("RAW Bayer", "Method", raw.bayersensor.method );
}
+ if (!pedited || pedited->raw.bayersensor.imageNum) {
+ keyFile.set_integer ("RAW Bayer", "ImageNum", raw.bayersensor.imageNum + 1 );
+ }
+
if (!pedited || pedited->raw.bayersensor.ccSteps) {
keyFile.set_integer ("RAW Bayer", "CcSteps", raw.bayersensor.ccSteps);
}
@@ -3364,7 +3403,121 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b
keyFile.set_integer ("RAW Bayer", "LMMSEIterations", raw.bayersensor.lmmse_iterations );
}
- //if (!pedited || pedited->raw.bayersensor.allEnhance) keyFile.set_boolean ("RAW Bayer", "ALLEnhance", raw.bayersensor.all_enhance );
+ if (!pedited || pedited->raw.bayersensor.pixelShiftMotion) {
+ keyFile.set_integer ("RAW Bayer", "PixelShiftMotion", raw.bayersensor.pixelShiftMotion );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftMotionCorrection) {
+ keyFile.set_integer ("RAW Bayer", "PixelShiftMotionCorrection", raw.bayersensor.pixelShiftMotionCorrection );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod) {
+ keyFile.set_integer ("RAW Bayer", "PixelShiftMotionCorrectionMethod", raw.bayersensor.pixelShiftMotionCorrectionMethod );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftStddevFactorGreen) {
+ keyFile.set_double ("RAW Bayer", "pixelShiftStddevFactorGreen", raw.bayersensor.pixelShiftStddevFactorGreen );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftStddevFactorRed) {
+ keyFile.set_double ("RAW Bayer", "pixelShiftStddevFactorRed", raw.bayersensor.pixelShiftStddevFactorRed );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftStddevFactorBlue) {
+ keyFile.set_double ("RAW Bayer", "pixelShiftStddevFactorBlue", raw.bayersensor.pixelShiftStddevFactorBlue );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftEperIso) {
+ keyFile.set_double ("RAW Bayer", "PixelShiftEperIso", raw.bayersensor.pixelShiftEperIso );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftNreadIso) {
+ keyFile.set_double ("RAW Bayer", "PixelShiftNreadIso", raw.bayersensor.pixelShiftNreadIso );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftPrnu) {
+ keyFile.set_double ("RAW Bayer", "PixelShiftPrnu", raw.bayersensor.pixelShiftPrnu );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftSigma) {
+ keyFile.set_double ("RAW Bayer", "PixelShiftSigma", raw.bayersensor.pixelShiftSigma );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftSum) {
+ keyFile.set_double ("RAW Bayer", "PixelShiftSum", raw.bayersensor.pixelShiftSum );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftRedBlueWeight) {
+ keyFile.set_double ("RAW Bayer", "PixelShiftRedBlueWeight", raw.bayersensor.pixelShiftRedBlueWeight );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelshiftShowMotion) {
+ keyFile.set_boolean ("RAW Bayer", "PixelShiftShowMotion", raw.bayersensor.pixelshiftShowMotion );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly) {
+ keyFile.set_boolean ("RAW Bayer", "PixelShiftShowMotionMaskOnly", raw.bayersensor.pixelshiftShowMotionMaskOnly );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftAutomatic) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftAutomatic", raw.bayersensor.pixelShiftAutomatic );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenHorizontal) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenHorizontal", raw.bayersensor.pixelShiftNonGreenHorizontal );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenVertical) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenVertical", raw.bayersensor.pixelShiftNonGreenVertical );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftHoleFill) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftHoleFill", raw.bayersensor.pixelShiftHoleFill );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftMedian) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftMedian", raw.bayersensor.pixelShiftMedian );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftMedian3) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftMedian3", raw.bayersensor.pixelShiftMedian3 );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftGreen) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftGreen", raw.bayersensor.pixelShiftGreen );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftBlur) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftBlur", raw.bayersensor.pixelShiftBlur );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftSmooth) {
+ keyFile.set_double ("RAW Bayer", "pixelShiftSmoothFactor", raw.bayersensor.pixelShiftSmoothFactor );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftExp0) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftExp0", raw.bayersensor.pixelShiftExp0 );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftLmmse) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftLmmse", raw.bayersensor.pixelShiftLmmse );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftEqualBright) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftEqualBright", raw.bayersensor.pixelShiftEqualBright );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenCross) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenCross", raw.bayersensor.pixelShiftNonGreenCross );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenCross2) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenCross2", raw.bayersensor.pixelShiftNonGreenCross2 );
+ }
+
+ if (!pedited || pedited->raw.bayersensor.pixelShiftNonGreenAmaze) {
+ keyFile.set_boolean ("RAW Bayer", "pixelShiftNonGreenAmaze", raw.bayersensor.pixelShiftNonGreenAmaze );
+ }
if (!pedited || pedited->raw.xtranssensor.method) {
keyFile.set_string ("RAW X-Trans", "Method", raw.xtranssensor.method );
@@ -7334,6 +7487,14 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited)
}
}
+ if (keyFile.has_key ("RAW Bayer", "ImageNum")) {
+ raw.bayersensor.imageNum = keyFile.get_integer ("RAW Bayer", "ImageNum") - 1;
+
+ if (pedited) {
+ pedited->raw.bayersensor.imageNum = true;
+ }
+ }
+
if (keyFile.has_key ("RAW Bayer", "CcSteps")) {
raw.bayersensor.ccSteps = keyFile.get_integer ("RAW Bayer", "CcSteps");
@@ -7422,7 +7583,237 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited)
}
}
- //if (keyFile.has_key ("RAW Bayer", "ALLEnhance")) { raw.bayersensor.all_enhance = keyFile.get_boolean("RAW Bayer", "ALLEnhance"); if (pedited) pedited->raw.bayersensor.allEnhance = true; }
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftMotion")) {
+ raw.bayersensor.pixelShiftMotion = keyFile.get_integer("RAW Bayer", "PixelShiftMotion");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftMotion = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftMotionCorrection")) {
+ raw.bayersensor.pixelShiftMotionCorrection = (RAWParams::BayerSensor::ePSMotionCorrection)keyFile.get_integer("RAW Bayer", "PixelShiftMotionCorrection");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftMotionCorrection = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftMotionCorrectionMethod")) {
+ raw.bayersensor.pixelShiftMotionCorrectionMethod = (RAWParams::BayerSensor::ePSMotionCorrectionMethod)keyFile.get_integer("RAW Bayer", "PixelShiftMotionCorrectionMethod");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftStddevFactorGreen")) {
+ raw.bayersensor.pixelShiftStddevFactorGreen = keyFile.get_double("RAW Bayer", "pixelShiftStddevFactorGreen");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftStddevFactorGreen = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftStddevFactorRed")) {
+ raw.bayersensor.pixelShiftStddevFactorRed = keyFile.get_double("RAW Bayer", "pixelShiftStddevFactorRed");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftStddevFactorRed = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftStddevFactorBlue")) {
+ raw.bayersensor.pixelShiftStddevFactorBlue = keyFile.get_double("RAW Bayer", "pixelShiftStddevFactorBlue");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftStddevFactorBlue = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftEperIso")) {
+ raw.bayersensor.pixelShiftEperIso = keyFile.get_double("RAW Bayer", "PixelShiftEperIso");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftEperIso = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftNreadIso")) {
+ raw.bayersensor.pixelShiftNreadIso = keyFile.get_double("RAW Bayer", "PixelShiftNreadIso");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftNreadIso = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftPrnu")) {
+ raw.bayersensor.pixelShiftPrnu = keyFile.get_double("RAW Bayer", "PixelShiftPrnu");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftPrnu = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftSigma")) {
+ raw.bayersensor.pixelShiftSigma = keyFile.get_double("RAW Bayer", "PixelShiftSigma");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftSigma = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftSum")) {
+ raw.bayersensor.pixelShiftSum = keyFile.get_double("RAW Bayer", "PixelShiftSum");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftSum = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftRedBlueWeight")) {
+ raw.bayersensor.pixelShiftRedBlueWeight = keyFile.get_double("RAW Bayer", "PixelShiftRedBlueWeight");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftRedBlueWeight = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftShowMotion")) {
+ raw.bayersensor.pixelshiftShowMotion = keyFile.get_boolean("RAW Bayer", "PixelShiftShowMotion");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelshiftShowMotion = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "PixelShiftShowMotionMaskOnly")) {
+ raw.bayersensor.pixelshiftShowMotionMaskOnly = keyFile.get_boolean("RAW Bayer", "PixelShiftShowMotionMaskOnly");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftAutomatic")) {
+ raw.bayersensor.pixelShiftAutomatic = keyFile.get_boolean("RAW Bayer", "pixelShiftAutomatic");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftAutomatic = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenHorizontal")) {
+ raw.bayersensor.pixelShiftNonGreenHorizontal = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenHorizontal");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftNonGreenHorizontal = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenVertical")) {
+ raw.bayersensor.pixelShiftNonGreenVertical = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenVertical");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftNonGreenVertical = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftHoleFill")) {
+ raw.bayersensor.pixelShiftHoleFill = keyFile.get_boolean("RAW Bayer", "pixelShiftHoleFill");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftHoleFill = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftMedian")) {
+ raw.bayersensor.pixelShiftMedian = keyFile.get_boolean("RAW Bayer", "pixelShiftMedian");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftMedian = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftMedian3")) {
+ raw.bayersensor.pixelShiftMedian3 = keyFile.get_boolean("RAW Bayer", "pixelShiftMedian3");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftMedian3 = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftGreen")) {
+ raw.bayersensor.pixelShiftGreen = keyFile.get_boolean("RAW Bayer", "pixelShiftGreen");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftGreen = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftBlur")) {
+ raw.bayersensor.pixelShiftBlur = keyFile.get_boolean("RAW Bayer", "pixelShiftBlur");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftBlur = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftSmoothFactor")) {
+ raw.bayersensor.pixelShiftSmoothFactor = keyFile.get_double("RAW Bayer", "pixelShiftSmoothFactor");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftSmooth = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftExp0")) {
+ raw.bayersensor.pixelShiftExp0 = keyFile.get_boolean("RAW Bayer", "pixelShiftExp0");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftExp0 = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftLmmse")) {
+ raw.bayersensor.pixelShiftLmmse = keyFile.get_boolean("RAW Bayer", "pixelShiftLmmse");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftLmmse = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftEqualBright")) {
+ raw.bayersensor.pixelShiftEqualBright = keyFile.get_boolean("RAW Bayer", "pixelShiftEqualBright");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftEqualBright = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenCross")) {
+ raw.bayersensor.pixelShiftNonGreenCross = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenCross");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftNonGreenCross = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenCross2")) {
+ raw.bayersensor.pixelShiftNonGreenCross2 = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenCross2");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftNonGreenCross2 = true;
+ }
+ }
+
+ if (keyFile.has_key ("RAW Bayer", "pixelShiftNonGreenAmaze")) {
+ raw.bayersensor.pixelShiftNonGreenAmaze = keyFile.get_boolean("RAW Bayer", "pixelShiftNonGreenAmaze");
+
+ if (pedited) {
+ pedited->raw.bayersensor.pixelShiftNonGreenAmaze = true;
+ }
+ }
}
// load X-Trans sensors' raw settings
@@ -7850,6 +8241,7 @@ bool ProcParams::operator== (const ProcParams& other)
&& resize.width == other.resize.width
&& resize.height == other.resize.height
&& raw.bayersensor.method == other.raw.bayersensor.method
+ && raw.bayersensor.imageNum == other.raw.bayersensor.imageNum
&& raw.bayersensor.ccSteps == other.raw.bayersensor.ccSteps
&& raw.bayersensor.black0 == other.raw.bayersensor.black0
&& raw.bayersensor.black1 == other.raw.bayersensor.black1
@@ -7858,8 +8250,38 @@ bool ProcParams::operator== (const ProcParams& other)
&& raw.bayersensor.twogreen == other.raw.bayersensor.twogreen
&& raw.bayersensor.greenthresh == other.raw.bayersensor.greenthresh
&& raw.bayersensor.linenoise == other.raw.bayersensor.linenoise
- && raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance
&& raw.bayersensor.dcb_iterations == other.raw.bayersensor.dcb_iterations
+ && raw.bayersensor.lmmse_iterations == other.raw.bayersensor.lmmse_iterations
+ && raw.bayersensor.pixelShiftMotion == other.raw.bayersensor.pixelShiftMotion
+ && raw.bayersensor.pixelShiftMotionCorrection == other.raw.bayersensor.pixelShiftMotionCorrection
+ && raw.bayersensor.pixelShiftMotionCorrectionMethod == other.raw.bayersensor.pixelShiftMotionCorrectionMethod
+ && raw.bayersensor.pixelShiftStddevFactorGreen == other.raw.bayersensor.pixelShiftStddevFactorGreen
+ && raw.bayersensor.pixelShiftStddevFactorRed == other.raw.bayersensor.pixelShiftStddevFactorRed
+ && raw.bayersensor.pixelShiftStddevFactorBlue == other.raw.bayersensor.pixelShiftStddevFactorBlue
+ && raw.bayersensor.pixelShiftEperIso == other.raw.bayersensor.pixelShiftEperIso
+ && raw.bayersensor.pixelShiftNreadIso == other.raw.bayersensor.pixelShiftNreadIso
+ && raw.bayersensor.pixelShiftPrnu == other.raw.bayersensor.pixelShiftPrnu
+ && raw.bayersensor.pixelShiftSigma == other.raw.bayersensor.pixelShiftSigma
+ && raw.bayersensor.pixelShiftSum == other.raw.bayersensor.pixelShiftSum
+ && raw.bayersensor.pixelShiftRedBlueWeight == other.raw.bayersensor.pixelShiftRedBlueWeight
+ && raw.bayersensor.pixelshiftShowMotion == other.raw.bayersensor.pixelshiftShowMotion
+ && raw.bayersensor.pixelshiftShowMotionMaskOnly == other.raw.bayersensor.pixelshiftShowMotionMaskOnly
+ && raw.bayersensor.pixelShiftAutomatic == other.raw.bayersensor.pixelShiftAutomatic
+ && raw.bayersensor.pixelShiftNonGreenHorizontal == other.raw.bayersensor.pixelShiftNonGreenHorizontal
+ && raw.bayersensor.pixelShiftNonGreenVertical == other.raw.bayersensor.pixelShiftNonGreenVertical
+ && raw.bayersensor.pixelShiftHoleFill == other.raw.bayersensor.pixelShiftHoleFill
+ && raw.bayersensor.pixelShiftMedian == other.raw.bayersensor.pixelShiftMedian
+ && raw.bayersensor.pixelShiftMedian3 == other.raw.bayersensor.pixelShiftMedian3
+ && raw.bayersensor.pixelShiftGreen == other.raw.bayersensor.pixelShiftGreen
+ && raw.bayersensor.pixelShiftBlur == other.raw.bayersensor.pixelShiftBlur
+ && raw.bayersensor.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor
+ && raw.bayersensor.pixelShiftExp0 == other.raw.bayersensor.pixelShiftExp0
+ && raw.bayersensor.pixelShiftLmmse == other.raw.bayersensor.pixelShiftLmmse
+ && raw.bayersensor.pixelShiftEqualBright == other.raw.bayersensor.pixelShiftEqualBright
+ && raw.bayersensor.pixelShiftNonGreenCross == other.raw.bayersensor.pixelShiftNonGreenCross
+ && raw.bayersensor.pixelShiftNonGreenCross2 == other.raw.bayersensor.pixelShiftNonGreenCross2
+ && raw.bayersensor.pixelShiftNonGreenAmaze == other.raw.bayersensor.pixelShiftNonGreenAmaze
+ && raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance
&& raw.xtranssensor.method == other.raw.xtranssensor.method
&& raw.xtranssensor.ccSteps == other.raw.xtranssensor.ccSteps
&& raw.xtranssensor.blackred == other.raw.xtranssensor.blackred
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 7cdc0894f..c83856870 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -1186,12 +1186,19 @@ public:
public:
//enum eMethod{ eahd,hphd,vng4,dcb,amaze,ahd,IGV_noise,fast,
//numMethods }; // This MUST be the last enum
- enum eMethod { amaze, igv, lmmse, eahd, hphd, vng4, dcb, ahd, fast, mono, none,
+ enum eMethod { amaze, igv, lmmse, eahd, hphd, vng4, dcb, ahd, fast, mono, none, pixelshift,
numMethods
}; // This MUST be the last enum
+ enum ePSMotionCorrection {
+ Grid1x1, Grid1x2, Grid3x3, Grid5x5, Grid7x7, Grid3x3New
+ };
+ enum ePSMotionCorrectionMethod {
+ Off, Automatic, Custom
+ };
static const char *methodstring[numMethods];
Glib::ustring method;
+ int imageNum;
int ccSteps;
double black0;
double black1;
@@ -1202,8 +1209,40 @@ public:
int greenthresh;
int dcb_iterations;
int lmmse_iterations;
+ int pixelShiftMotion;
+ ePSMotionCorrection pixelShiftMotionCorrection;
+ ePSMotionCorrectionMethod pixelShiftMotionCorrectionMethod;
+ double pixelShiftStddevFactorGreen;
+ double pixelShiftStddevFactorRed;
+ double pixelShiftStddevFactorBlue;
+ double pixelShiftEperIso;
+ double pixelShiftNreadIso;
+ double pixelShiftPrnu;
+ double pixelShiftSigma;
+ double pixelShiftSum;
+ double pixelShiftRedBlueWeight;
+ bool pixelshiftShowMotion;
+ bool pixelshiftShowMotionMaskOnly;
+ bool pixelShiftAutomatic;
+ bool pixelShiftNonGreenHorizontal;
+ bool pixelShiftNonGreenVertical;
+ bool pixelShiftHoleFill;
+ bool pixelShiftMedian;
+ bool pixelShiftMedian3;
+ bool pixelShiftGreen;
+ bool pixelShiftBlur;
+ double pixelShiftSmoothFactor;
+ bool pixelShiftExp0;
+ bool pixelShiftLmmse;
+ bool pixelShiftEqualBright;
+ bool pixelShiftNonGreenCross;
+ bool pixelShiftNonGreenCross2;
+ bool pixelShiftNonGreenAmaze;
bool dcb_enhance;
//bool all_enhance;
+
+ void setPixelShiftDefaults();
+
};
/**
diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc
index 88fed5473..2cd1abf5f 100644
--- a/rtengine/rawimage.cc
+++ b/rtengine/rawimage.cc
@@ -400,7 +400,7 @@ skip_block:
}
}
-int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistener, double progressRange)
+int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, ProgressListener *plistener, double progressRange)
{
ifname = filename.c_str();
image = nullptr;
@@ -424,7 +424,12 @@ int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistene
raw_image = nullptr;
//***************** Read ALL raw file info
- identify ();
+ // set the number of the frame to extract. If the number is larger then number of existing frames - 1, dcraw will handle that correctly
+
+ shot_select = imageNum;
+ identify();
+ // in case dcraw didn't handle the above mentioned case...
+ shot_select = std::min(shot_select, std::max(is_raw, 1u) - 1);
if (!is_raw) {
fclose(ifp);
@@ -660,7 +665,7 @@ int RawImage::loadRaw (bool loadData, bool closeFile, ProgressListener *plistene
return 0;
}
-float** RawImage::compress_image()
+float** RawImage::compress_image(int frameNum)
{
if( !image ) {
return nullptr;
@@ -668,11 +673,12 @@ float** RawImage::compress_image()
if (isBayer() || isXtrans()) {
if (!allocation) {
- allocation = new float[height * width];
+ // shift the beginning of all frames but the first by 32 floats to avoid cache miss conflicts on CPUs which have <= 4-way associative L1-Cache
+ allocation = new float[height * width + frameNum * 32];
data = new float*[height];
for (int i = 0; i < height; i++) {
- data[i] = allocation + i * width;
+ data[i] = allocation + i * width + frameNum * 32;
}
}
} else if (colors == 1) {
diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h
index 804a2a346..3f4307054 100644
--- a/rtengine/rawimage.h
+++ b/rtengine/rawimage.h
@@ -106,7 +106,7 @@ public:
explicit RawImage( const Glib::ustring &name );
~RawImage();
- int loadRaw (bool loadData = true, bool closeFile = true, ProgressListener *plistener = nullptr, double progressRange = 1.0);
+ int loadRaw (bool loadData, unsigned int imageNum = 0, bool closeFile = true, ProgressListener *plistener = nullptr, double progressRange = 1.0);
void get_colorsCoeff( float* pre_mul_, float* scale_mul_, float* cblack_, bool forceAutoWB );
void set_prefilters()
{
@@ -119,9 +119,10 @@ public:
{
return image;
}
- float** compress_image(); // revert to compressed pixels format and release image data
+ float** compress_image(int frameNum); // revert to compressed pixels format and release image data
float** data; // holds pixel values, data[i][j] corresponds to the ith row and jth column
unsigned prefilters; // original filters saved ( used for 4 color processing )
+ unsigned int getFrameCount() const { return is_raw; }
protected:
Glib::ustring filename; // complete filename
int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index 9678fcaf5..28d3c1e89 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -37,7 +37,7 @@
#include
#endif
#include "opthelper.h"
-//#define BENCHMARK
+#define BENCHMARK
#include "StopWatch.h"
#define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val )
#undef CLIPD
@@ -475,8 +475,12 @@ RawImageSource::~RawImageSource ()
delete idata;
- if (ri) {
- delete ri;
+ for(size_t i = 0; i < numFrames; ++i) {
+ delete riFrames[i];
+ }
+
+ for(size_t i = 0; i < numFrames - 1; ++i) {
+ delete rawDataBuffer[i];
}
flushRGB();
@@ -913,7 +917,7 @@ void RawImageSource::convertColorSpace(Imagefloat* image, const ColorManagementP
/* interpolateBadPixelsBayer: correct raw pixels looking at the bitmap
* takes into consideration if there are multiple bad pixels in the neighbourhood
*/
-int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads )
+int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads, array2D &rawData )
{
static const float eps = 1.f;
int counter = 0;
@@ -1494,7 +1498,7 @@ void RawImageSource::vflip (Imagefloat* image)
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-int RawImageSource::load (const Glib::ustring &fname, bool batch)
+int RawImageSource::load (const Glib::ustring &fname, int imageNum, bool batch)
{
MyTime t1, t2;
@@ -1505,15 +1509,50 @@ int RawImageSource::load (const Glib::ustring &fname, bool batch)
plistener->setProgressStr ("Decoding...");
plistener->setProgress (0.0);
}
-
ri = new RawImage(fname);
- int errCode = ri->loadRaw (true, true, plistener, 0.8);
+ int errCode = ri->loadRaw (false, 0, false);
if (errCode) {
return errCode;
}
+ numFrames = ri->getFrameCount();
- ri->compress_image();
+ errCode = 0;
+#ifdef _OPENMP
+#pragma omp parallel if(numFrames > 1)
+#endif
+{
+ int errCodeThr = 0;
+#ifdef _OPENMP
+#pragma omp for nowait
+#endif
+ for(unsigned int i = 0; i < numFrames; ++i) {
+ if(i == 0) {
+ riFrames[i] = ri;
+ errCodeThr = riFrames[i]->loadRaw (true, i, true, plistener, 0.8);
+ } else {
+ riFrames[i] = new RawImage(fname);
+ errCodeThr = riFrames[i]->loadRaw (true, i);
+ }
+ riFrames[i]->compress_image(i);
+ }
+#ifdef _OPENMP
+#pragma omp critical
+#endif
+{
+ errCode = errCodeThr ? errCodeThr : errCode;
+}
+
+}
+ if(errCode) {
+ return errCode;
+ }
+
+ if(numFrames > 1 ) { // this disables multi frame support for Fuji S5 until I found a solution to handle different dimensions
+ if(riFrames[0]->get_width() != riFrames[1]->get_width() || riFrames[0]->get_height() != riFrames[1]->get_height()) {
+ numFrames = 1;
+ }
+ }
if (plistener) {
plistener->setProgress (0.9);
@@ -1626,8 +1665,10 @@ int RawImageSource::load (const Glib::ustring &fname, bool batch)
initialGain = 1.0 / min(pre_mul[0], pre_mul[1], pre_mul[2]);
}*/
+ for(unsigned int i = 0;i < numFrames; ++i) {
+ riFrames[i]->set_prefilters();
+ }
- ri->set_prefilters();
//Load complete Exif informations
RawMetaDataLocation rml;
@@ -1719,7 +1760,24 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
printf( "Flat Field Correction:%s\n", rif->get_filename().c_str());
}
- copyOriginalPixels(raw, ri, rid, rif);
+ if(numFrames == 4) {
+ int bufferNumber = 0;
+ for(int i=0; i<4; ++i) {
+ if(i==currFrame) {
+ copyOriginalPixels(raw, ri, rid, rif, rawData);
+ rawDataFrames[i] = &rawData;
+ } else {
+ if(!rawDataBuffer[bufferNumber]) {
+ rawDataBuffer[bufferNumber] = new array2D;
+ }
+ rawDataFrames[i] = rawDataBuffer[bufferNumber];
+ ++bufferNumber;
+ copyOriginalPixels(raw, riFrames[i], rid, rif, *rawDataFrames[i]);
+ }
+ }
+ } else {
+ copyOriginalPixels(raw, ri, rid, rif, rawData);
+ }
//FLATFIELD end
@@ -1759,8 +1817,13 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
}
}
-
- scaleColors( 0, 0, W, H, raw); //+ + raw parameters for black level(raw.blackxx)
+ if(numFrames == 4) {
+ for(int i=0; i<4; ++i) {
+ scaleColors( 0, 0, W, H, raw, *rawDataFrames[i]);
+ }
+ } else {
+ scaleColors( 0, 0, W, H, raw, rawData); //+ + raw parameters for black level(raw.blackxx)
+ }
// Correct vignetting of lens profile
if (!hasFlatField && lensProf.useVign) {
@@ -1770,13 +1833,25 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
LCPMapper map(pLCPProf, max(idata->getFocalLen(), 1.0), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1);
if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) {
-
+ if(numFrames == 4) {
+ for(int i = 0; i < 4; ++i) {
#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16)
+ #pragma omp parallel for schedule(dynamic,16)
#endif
- for (int y = 0; y < H; y++) {
- map.processVignetteLine(W, y, rawData[y]);
+ for (int y = 0; y < H; y++) {
+ map.processVignetteLine(W, y, (*rawDataFrames[i])[y]);
+ }
+ }
+ } else {
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int y = 0; y < H; y++) {
+ map.processVignetteLine(W, y, rawData[y]);
+ }
}
} else if(ri->get_colors() == 3) {
#ifdef _OPENMP
@@ -1854,13 +1929,25 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
plistener->setProgress (0.0);
}
- green_equilibrate(0.01 * (raw.bayersensor.greenthresh));
+ if(numFrames == 4) {
+ for(int i = 0; i < 4; ++i) {
+ green_equilibrate(0.01 * (raw.bayersensor.greenthresh), *rawDataFrames[i]);
+ }
+ } else {
+ green_equilibrate(0.01 * (raw.bayersensor.greenthresh), rawData);
+ }
}
if( totBP ) {
if ( ri->getSensorType() == ST_BAYER ) {
- interpolateBadPixelsBayer( *bitmapBads );
+ if(numFrames == 4) {
+ for(int i = 0; i < 4; ++i) {
+ interpolateBadPixelsBayer( *bitmapBads, *rawDataFrames[i] );
+ }
+ } else {
+ interpolateBadPixelsBayer( *bitmapBads, rawData );
+ }
} else if ( ri->getSensorType() == ST_FUJI_XTRANS ) {
interpolateBadPixelsXtrans( *bitmapBads );
} else {
@@ -1882,12 +1969,23 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
plistener->setProgressStr ("CA Auto Correction...");
plistener->setProgress (0.0);
}
-
- CA_correct_RT(raw.cared, raw.cablue, 10.0 - raw.caautostrength);
+ if(numFrames == 4 && raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::pixelshift]) {
+ for(int i=0; i<4; ++i) {
+ CA_correct_RT(raw.cared, raw.cablue, 10.0 - raw.caautostrength, *rawDataFrames[i]);
+ }
+ } else {
+ CA_correct_RT(raw.cared, raw.cablue, 10.0 - raw.caautostrength, rawData);
+ }
}
if ( raw.expos != 1 ) {
- processRawWhitepoint(raw.expos, raw.preser);
+ if(numFrames == 4) {
+ for(int i = 0; i < 4; ++i) {
+ processRawWhitepoint(raw.expos, raw.preser, *rawDataFrames[i]);
+ }
+ } else {
+ processRawWhitepoint(raw.expos, raw.preser, rawData);
+ }
}
if(prepareDenoise && dirpyrdenoiseExpComp == INFINITY) {
@@ -1926,7 +2024,142 @@ void RawImageSource::demosaic(const RAWParams &raw)
} else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::ahd] ) {
ahd_demosaic (0, 0, W, H);
} else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::amaze] ) {
- amaze_demosaic_RT (0, 0, W, H);
+ amaze_demosaic_RT (0, 0, W, H, rawData, red, green, blue);
+ } else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::pixelshift] ) {
+ if(numFrames != 4) { // fallback for non pixelshift files
+ amaze_demosaic_RT (0, 0, W, H, rawData, red, green, blue);
+ } else {
+ RAWParams::BayerSensor bayerParams = raw.bayersensor;
+ if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Automatic) {
+ bool pixelShiftEqualBright = bayerParams.pixelShiftEqualBright;
+ bayerParams.setPixelShiftDefaults();
+ bayerParams.pixelShiftEqualBright = pixelShiftEqualBright;
+ } else if(bayerParams.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Off) {
+ bayerParams.pixelShiftMotion = 0;
+ bayerParams.pixelShiftAutomatic = false;
+ bayerParams.pixelshiftShowMotion = false;
+ }
+ 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
+#ifdef PIXELSHIFTDEV
+ if(!bayerParams.pixelShiftMedian3) {
+#endif
+ if(bayerParams.pixelShiftLmmse) {
+ lmmse_interpolate_omp(W, H, *(rawDataFrames[0]), red, green, blue, raw.bayersensor.lmmse_iterations);
+ } else {
+ amaze_demosaic_RT (0, 0, W, H, *(rawDataFrames[0]), red, green, blue);
+ }
+ multi_array2D redTmp(W,H);
+ multi_array2D greenTmp(W,H);
+ multi_array2D blueTmp(W,H);
+ for(int i=0;i<3;i++) {
+ if(bayerParams.pixelShiftLmmse) {
+ lmmse_interpolate_omp(W, H, *(rawDataFrames[i+1]), redTmp[i], greenTmp[i], blueTmp[i], raw.bayersensor.lmmse_iterations);
+ } else {
+ amaze_demosaic_RT (0, 0, W, H, *(rawDataFrames[i+1]), redTmp[i], greenTmp[i], blueTmp[i]);
+ }
+ }
+ #pragma omp parallel for schedule(dynamic,16)
+ for(int i=border;i redTmp(W,H);
+ multi_array2D greenTmp(W,H);
+ multi_array2D blueTmp(W,H);
+ for(int i=0, frameIndex = 0;i<4;++i) {
+ if(i != currFrame) {
+ if(bayerParams.pixelShiftLmmse) {
+ lmmse_interpolate_omp(W, H, *(rawDataFrames[i]), redTmp[frameIndex], greenTmp[frameIndex], blueTmp[frameIndex], raw.bayersensor.lmmse_iterations);
+ } else {
+ amaze_demosaic_RT (0, 0, W, H, *(rawDataFrames[i]), redTmp[frameIndex], greenTmp[frameIndex], blueTmp[frameIndex]);
+ }
+ ++frameIndex;
+ }
+ }
+ unsigned int offsX0 = 0, offsY0 = 0;
+ unsigned int offsX1 = 0, offsY1 = 0;
+ unsigned int offsX2 = 0, offsY2 = 0;
+
+ // We have to adjust the offsets for the selected subframe we exclude from median
+ switch (currFrame) {
+ case 0:
+ offsY0 = 1;
+ offsX0 = 0;
+ offsY1 = 1;
+ offsX1 = 1;
+ offsY2 = 0;
+ offsX2 = 1;
+ break;
+
+ case 1:
+ offsY0 = 0;
+ offsX0 = 0;
+ offsY1 = 1;
+ offsX1 = 1;
+ offsY2 = 0;
+ offsX2 = 1;
+ break;
+
+ case 2:
+ offsY0 = 0;
+ offsX0 = 0;
+ offsY1 = 1;
+ offsX1 = 0;
+ offsY2 = 0;
+ offsX2 = 1;
+ break;
+
+ case 3:
+ offsY0 = 0;
+ offsX0 = 0;
+ offsY1 = 1;
+ offsX1 = 0;
+ offsY2 = 1;
+ offsX2 = 1;
+ }
+
+ #pragma omp parallel for schedule(dynamic,16)
+ for(int i=border;iget_model(), raw.expos);
+ }
} else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::dcb] ) {
dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance);
} else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::eahd]) {
@@ -1934,7 +2167,7 @@ void RawImageSource::demosaic(const RAWParams &raw)
} else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::igv]) {
igv_interpolate(W, H);
} else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::lmmse]) {
- lmmse_interpolate_omp(W, H, raw.bayersensor.lmmse_iterations);
+ lmmse_interpolate_omp(W, H, rawData, red, green, blue, raw.bayersensor.lmmse_iterations);
} else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::fast] ) {
fast_demosaic (0, 0, W, H);
} else if (raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono] ) {
@@ -2973,7 +3206,7 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
/* Copy original pixel data and
* subtract dark frame (if present) from current image and apply flat field correction (if present)
*/
-void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, RawImage *riDark, RawImage *riFlatFile )
+void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, RawImage *riDark, RawImage *riFlatFile, array2D &rawData )
{
// TODO: Change type of black[] to float to avoid conversions
unsigned short black[4] = {
@@ -3304,7 +3537,7 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur
// Scale original pixels into the range 0 65535 using black offsets and multipliers
-void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw)
+void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw, array2D &rawData)
{
chmax[0] = chmax[1] = chmax[2] = chmax[3] = 0; //channel maxima
float black_lev[4] = {0.f};//black level
@@ -5235,6 +5468,36 @@ void RawImageSource::init ()
}
}
+void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int &B)
+{
+ int xnew = x + border;
+ int ynew = y + border;
+ rotate += ri->get_rotateDegree();
+ rotate %= 360;
+ if (rotate == 90) {
+ std::swap(xnew,ynew);
+ ynew = H - 1 - ynew;
+ } else if (rotate == 180) {
+ xnew = W - 1 - xnew;
+ ynew = H - 1 - ynew;
+ } else if (rotate == 270) {
+ std::swap(xnew,ynew);
+ ynew = H - 1 - ynew;
+ xnew = W - 1 - xnew;
+ ynew = H - 1 - ynew;
+ }
+
+ int c = ri->getSensorType() == ST_FUJI_XTRANS ? ri->XTRANSFC(ynew,xnew) : ri->FC(ynew,xnew);
+ int val = round(rawData[ynew][xnew] / scale_mul[c]);
+ if(c == 0) {
+ R = val; G = 0; B = 0;
+ } else if(c == 2) {
+ R = 0; G = 0; B = val;
+ } else {
+ R = 0; G = val; B = 0;
+ }
+}
+
void RawImageSource::cleanup ()
{
delete phaseOneIccCurve;
diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h
index 9fafef8bb..cac29c138 100644
--- a/rtengine/rawimagesource.h
+++ b/rtengine/rawimagesource.h
@@ -25,7 +25,7 @@
#include "curves.h"
#include "color.h"
#include "iimage.h"
-
+#include
#define HR_SCALE 2
namespace rtengine
@@ -71,6 +71,9 @@ protected:
bool rgbSourceModified;
RawImage* ri; // Copy of raw pixels, NOT corrected for initial gain, blackpoint etc.
+ RawImage* riFrames[4] = {nullptr};
+ unsigned int currFrame = 0;
+ unsigned int numFrames = 0;
// to accelerate CIELAB conversion:
double lc00, lc01, lc02, lc10, lc11, lc12, lc20, lc21, lc22;
@@ -78,6 +81,8 @@ protected:
int threshold;
array2D rawData; // holds preprocessed pixel values, rowData[i][j] corresponds to the ith row and jth column
+ array2D *rawDataFrames[4] = {nullptr};
+ array2D *rawDataBuffer[3] = {nullptr};
// the interpolated green plane:
array2D green;
@@ -107,7 +112,7 @@ public:
RawImageSource ();
~RawImageSource ();
- int load (const Glib::ustring &fname, bool batch = false);
+ int load (const Glib::ustring &fname, int imageNum = 0, bool batch = false);
void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true);
void demosaic (const RAWParams &raw);
void retinex (ColorManagementParams cmp, RetinexParams deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI);
@@ -125,9 +130,9 @@ public:
}
void processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4]);
- void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile );
+ void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile, array2D &rawData );
void cfaboxblur (RawImage *riFlatFile, float* cfablur, int boxH, int boxW);
- void scaleColors (int winx, int winy, int winw, int winh, const RAWParams &raw); // raw for cblack
+ void scaleColors (int winx, int winy, int winw, int winh, const RAWParams &raw, array2D &rawData); // raw for cblack
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const ColorManagementParams &cmp, const RAWParams &raw);
eSensorType getSensorType () const
@@ -195,7 +200,10 @@ public:
static void HLRecovery_blend (float* rin, float* gin, float* bin, int width, float maxval, float* hlmax);
static void init ();
static void cleanup ();
-
+ void setCurrentFrame(unsigned int frameNum) {
+ currFrame = std::min(numFrames - 1, frameNum);
+ ri = riFrames[currFrame];
+ }
protected:
typedef unsigned short ushort;
void processFalseColorCorrection (Imagefloat* i, const int steps);
@@ -208,18 +216,18 @@ protected:
inline void interpolate_row_rb (float* ar, float* ab, float* pg, float* cg, float* ng, int i);
inline void interpolate_row_rb_mul_pp (float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip);
- void CA_correct_RT (const double cared, const double cablue, const double caautostrength);
+ void CA_correct_RT (const double cared, const double cablue, const double caautostrength, array2D &rawData);
void ddct8x8s(int isgn, float a[8][8]);
- void processRawWhitepoint (float expos, float preser); // exposure before interpolation
+ void processRawWhitepoint (float expos, float preser, array2D &rawData); // exposure before interpolation
- int interpolateBadPixelsBayer( PixelsMap &bitmapBads );
+ int interpolateBadPixelsBayer( PixelsMap &bitmapBads, array2D &rawData );
int interpolateBadPixelsNColours( PixelsMap &bitmapBads, const int colours );
int interpolateBadPixelsXtrans( PixelsMap &bitmapBads );
int findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels );
void cfa_linedn (float linenoiselevel);//Emil's line denoise
- void green_equilibrate (float greenthresh);//Emil's green equilibration
+ void green_equilibrate (float greenthresh, array2D &rawData);//Emil's green equilibration
void nodemosaic(bool bw);
void eahd_demosaic();
@@ -228,8 +236,8 @@ protected:
void ppg_demosaic();
void jdl_interpolate_omp();
void igv_interpolate(int winw, int winh);
- void lmmse_interpolate_omp(int winw, int winh, int iterations);
- void amaze_demosaic_RT(int winx, int winy, int winw, int winh);//Emil's code for AMaZE
+ void lmmse_interpolate_omp(int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue, int iterations);
+ void amaze_demosaic_RT(int winx, int winy, int winw, int winh, array2D &rawData, array2D &red, array2D &green, array2D &blue);//Emil's code for AMaZE
void fast_demosaic(int winx, int winy, int winw, int winh );//Emil's code for fast demosaicing
void dcb_demosaic(int iterations, bool dcb_enhance);
void ahd_demosaic(int winx, int winy, int winw, int winh);
@@ -253,8 +261,10 @@ protected:
void xtransborder_interpolate (int border);
void xtrans_interpolate (const int passes, const bool useCieLab);
void fast_xtrans_interpolate ();
+ void pixelshift(int winx, int winy, int winw, int winh, const RAWParams::BayerSensor &bayerParams, unsigned int frame, const std::string &model, float rawWpCorrection);
void hflip (Imagefloat* im);
void vflip (Imagefloat* im);
+ void getRawValues(int x, int y, int rotate, int &R, int &G, int &B);
};
}
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index 8e832a734..0bb188b5d 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -470,7 +470,37 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
RETINEX, // EvRetinexgaintransmission
RETINEX, // EvLskal
OUTPUTPROFILE, // EvOBPCompens
- ALLNORAW // EvWBtempBias
+ ALLNORAW, // EvWBtempBias
+ DARKFRAME, // EvRawImageNum
+ DEMOSAIC, // EvPixelShiftMotion
+ DEMOSAIC, // EvPixelShiftMotionCorrection
+ DEMOSAIC, // EvPixelShiftStddevFactorGreen
+ DEMOSAIC, // EvPixelShiftEperIso
+ DEMOSAIC, // EvPixelShiftNreadIso
+ DEMOSAIC, // EvPixelShiftPrnu
+ DEMOSAIC, // EvPixelshiftShowMotion
+ DEMOSAIC, // EvPixelshiftShowMotionMaskOnly
+ DEMOSAIC, // EvPixelShiftAutomatic
+ DEMOSAIC, // EvPixelShiftNonGreenHorizontal
+ DEMOSAIC, // EvPixelShiftNonGreenVertical
+ DEMOSAIC, // EvPixelShiftNonGreenCross
+ DEMOSAIC, // EvPixelShiftStddevFactorRed
+ DEMOSAIC, // EvPixelShiftStddevFactorBlue
+ DEMOSAIC, // EvPixelShiftNonGreenCross2
+ DEMOSAIC, // EvPixelShiftNonGreenAmaze
+ DEMOSAIC, // EvPixelShiftGreen
+ DEMOSAIC, // EvPixelShiftRedBlueWeight
+ DEMOSAIC, // EvPixelShiftBlur
+ DEMOSAIC, // EvPixelShiftSigma
+ DEMOSAIC, // EvPixelShiftSum
+ DEMOSAIC, // EvPixelShiftExp0
+ DEMOSAIC, // EvPixelShiftHoleFill
+ DEMOSAIC, // EvPixelShiftMedian
+ DEMOSAIC, // EvPixelShiftMedian3
+ DEMOSAIC, // EvPixelShiftMotionMethod
+ DEMOSAIC, // EvPixelShiftSmooth
+ DEMOSAIC, // EvPixelShiftLmmse
+ DEMOSAIC // EvPixelShiftEqualBright
};
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index b30f8a915..890ad0bcb 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -176,7 +176,8 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode)
{
RawImage *ri = new RawImage(fname);
- int r = ri->loadRaw(false, false);
+ unsigned int imageNum = 0;
+ int r = ri->loadRaw(false, imageNum, false);
if( r ) {
delete ri;
@@ -290,7 +291,9 @@ RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname)
rml.ciffLength = -1;
RawImage ri(fname);
- int r = ri.loadRaw(false);
+ unsigned int imageNum = 0;
+
+ int r = ri.loadRaw(false, imageNum);
if( !r ) {
rml.exifBase = ri.get_exifBase();
@@ -301,10 +304,12 @@ RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname)
return rml;
}
-Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate)
+Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum)
{
RawImage *ri = new RawImage (fname);
- int r = ri->loadRaw(1, 0);
+ unsigned int tempImageNum = 0;
+
+ int r = ri->loadRaw(1, tempImageNum, 0);
if( r ) {
delete ri;
diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h
index 56e68f815..c40a226c4 100644
--- a/rtengine/rtthumbnail.h
+++ b/rtengine/rtthumbnail.h
@@ -78,7 +78,7 @@ public:
void getDimensions (int& w, int& h, double& scaleFac);
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false);
- static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate);
+ static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum);
static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode = false);
static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname);
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 9f1ca3c5c..35515923b 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -102,6 +102,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
ImProcFunctions ipf (¶ms, true);
PreviewProps pp (0, 0, fw, fh, 1);
+ imgsrc->setCurrentFrame(params.raw.bayersensor.imageNum);
imgsrc->preprocess( params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled);
if (params.toneCurve.autoexp) {// this enabled HLRecovery
diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc
index 1ef4bf884..887f1c3ff 100644
--- a/rtengine/stdimagesource.cc
+++ b/rtengine/stdimagesource.cc
@@ -102,7 +102,7 @@ void StdImageSource::getSampleFormat (const Glib::ustring &fname, IIOSampleForma
* and RT's image data type (Image8, Image16 and Imagefloat), then it will
* load the image into it
*/
-int StdImageSource::load (const Glib::ustring &fname, bool batch)
+int StdImageSource::load (const Glib::ustring &fname, int imageNum, bool batch)
{
fileName = fname;
diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h
index 0ef487a75..1dbddf325 100644
--- a/rtengine/stdimagesource.h
+++ b/rtengine/stdimagesource.h
@@ -42,7 +42,7 @@ public:
StdImageSource ();
~StdImageSource ();
- int load (const Glib::ustring &fname, bool batch = false);
+ int load (const Glib::ustring &fname, int imageNum = 0, bool batch = false);
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const ColorManagementParams &cmp, const RAWParams &raw);
ColorTemp getWB () const
{
@@ -95,6 +95,11 @@ public:
{
return rgbSourceModified;
}
+ void setCurrentFrame(unsigned int frameNum) {}
+
+ void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) { R = G = B = 0;}
+
+
};
}
#endif
diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc
index 9fc6b6fb6..13dca86b1 100644
--- a/rtexif/pentaxattribs.cc
+++ b/rtexif/pentaxattribs.cc
@@ -42,6 +42,7 @@ public:
choices[3] = "TIFF";
choices[4] = "RAW";
choices[5] = "Premium";
+ choices[6] = "RAW (HDR enabled)";
choices[7] = "RAW (pixel shift enabled)";
choices[65535] = "n/a";
}
diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc
index e1bf790a6..5c559fc1f 100644
--- a/rtgui/bayerprocess.cc
+++ b/rtgui/bayerprocess.cc
@@ -38,6 +38,30 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA
hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4);
pack_start( *hb1, Gtk::PACK_SHRINK, 4);
+ imageNumberBox = Gtk::manage (new Gtk::HBox ());
+ imageNumberBox->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_IMAGENUM") + ": ")), Gtk::PACK_SHRINK, 4);
+ imageNumber = Gtk::manage (new MyComboBoxText ());
+ imageNumber->append("1");
+ imageNumber->append("2");
+ imageNumber->append("3");
+ imageNumber->append("4");
+ imageNumber->set_active(0);
+ imageNumberBox->set_tooltip_text(M("TP_RAW_IMAGENUM_TOOLTIP"));
+ imageNumberBox->pack_end (*imageNumber, Gtk::PACK_EXPAND_WIDGET, 4);
+ pack_start( *imageNumberBox, Gtk::PACK_SHRINK, 4);
+
+ pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 );
+ ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 ));
+ ccSteps->setAdjusterListener (this);
+
+ if (ccSteps->delay < options.adjusterMaxDelay) {
+ ccSteps->delay = options.adjusterMaxDelay;
+ }
+
+ ccSteps->show();
+ pack_start( *ccSteps, Gtk::PACK_SHRINK, 4);
+
+
dcbOptions = Gtk::manage (new Gtk::VBox ());
dcbIterations = Gtk::manage (new Adjuster (M("TP_RAW_DCBITERATIONS"), 0, 5, 1, 2));
@@ -48,7 +72,7 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA
}
dcbIterations->show();
- dcbEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_DCBENHANCE")));
+ dcbEnhance = Gtk::manage (new MyCheckButton(M("TP_RAW_DCBENHANCE")));
dcbOptions->pack_start(*dcbIterations);
dcbOptions->pack_start(*dcbEnhance);
pack_start( *dcbOptions, Gtk::PACK_SHRINK, 4);
@@ -67,92 +91,422 @@ BayerProcess::BayerProcess () : FoldableToolPanel(this, "bayerprocess", M("TP_RA
lmmseOptions->pack_start(*lmmseIterations);
pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4);
- pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 );
- ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"), 0, 5, 1, 0 ));
- ccSteps->setAdjusterListener (this);
+ pixelShiftFrame = Gtk::manage (new Gtk::VBox ());
+ pixelShiftFrame->set_border_width(0);
- if (ccSteps->delay < options.adjusterMaxDelay) {
- ccSteps->delay = options.adjusterMaxDelay;
+ pixelShiftEqualBright = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTEQUALBRIGHT")));
+ pixelShiftEqualBright->set_tooltip_text (M("TP_RAW_PIXELSHIFTEQUALBRIGHT_TOOLTIP"));
+ pixelShiftFrame->pack_start(*pixelShiftEqualBright);
+
+ Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ());
+ hb3->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_PIXELSHIFTMOTIONMETHOD") + ": ")), Gtk::PACK_SHRINK, 4);
+ pixelShiftMotionMethod = Gtk::manage (new MyComboBoxText ());
+ pixelShiftMotionMethod->append("Off");
+ pixelShiftMotionMethod->append("Automatic");
+ pixelShiftMotionMethod->append("Custom");
+ pixelShiftMotionMethod->set_active(1);
+ pixelShiftMotionMethod->show();
+ hb3->pack_start(*pixelShiftMotionMethod);
+ pixelShiftFrame->pack_start(*hb3);
+
+ pixelShiftOptions = Gtk::manage (new Gtk::VBox ());
+ pixelShiftOptions->set_border_width(0);
+
+ pixelShiftShowMotion = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTSHOWMOTION")));
+ pixelShiftShowMotion->set_tooltip_text (M("TP_RAW_PIXELSHIFTSHOWMOTION_TOOLTIP"));
+ pixelShiftFrame->pack_start(*pixelShiftShowMotion);
+
+ pixelShiftShowMotionMaskOnly = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY")));
+ pixelShiftShowMotionMaskOnly->set_tooltip_text (M("TP_RAW_PIXELSHIFTSHOWMOTIONMASKONLY_TOOLTIP"));
+ pixelShiftFrame->pack_start(*pixelShiftShowMotionMaskOnly);
+
+#ifdef PIXELSHIFTDEV
+ pixelShiftAutomatic = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTADAPTIVE")));
+ pixelShiftOptions->pack_start(*pixelShiftAutomatic);
+#endif
+ pixelShiftGreen = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTGREEN")));
+ pixelShiftOptions->pack_start(*pixelShiftGreen);
+
+ pixelShiftNonGreenCross = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTNONGREENCROSS")));
+ pixelShiftOptions->pack_start(*pixelShiftNonGreenCross);
+
+ pixelShiftHoleFill = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTHOLEFILL")));
+ pixelShiftHoleFill->set_tooltip_text (M("TP_RAW_PIXELSHIFTHOLEFILL_TOOLTIP"));
+ pixelShiftOptions->pack_start(*pixelShiftHoleFill);
+
+ pixelShiftBlur = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTBLUR")));
+ pixelShiftBlur->set_tooltip_text (M("TP_RAW_PIXELSHIFTSIGMA_TOOLTIP"));
+ pixelShiftOptions->pack_start(*pixelShiftBlur);
+
+ pixelShiftSigma = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSIGMA"), 0.5, 25, 0.1, 1.0));
+ pixelShiftSigma->set_tooltip_text (M("TP_RAW_PIXELSHIFTSIGMA_TOOLTIP"));
+ pixelShiftSigma->setAdjusterListener (this);
+
+ if (pixelShiftSigma->delay < options.adjusterMaxDelay) {
+ pixelShiftSigma->delay = options.adjusterMaxDelay;
}
- ccSteps->show();
- pack_start( *ccSteps, Gtk::PACK_SHRINK, 4);
+ pixelShiftSigma->show();
+ pixelShiftOptions->pack_start(*pixelShiftSigma);
- //pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0 );
- //allOptions = Gtk::manage (new Gtk::VBox ());
- //allEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_ALLENHANCE")));
- //allOptions->pack_start(*allEnhance);
- //pack_start( *allOptions, Gtk::PACK_SHRINK, 4);
- methodconn = method->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::methodChanged) );
- dcbEnhconn = dcbEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::dcbEnhanceChanged), true);
- //allEnhconn = allEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::allEnhanceChanged), true);
+ 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);
+
+ pixelShiftEperIso = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTEPERISO"), -5.0, 5.0, 0.05, 0.0));
+ pixelShiftEperIso->set_tooltip_text(M("TP_RAW_PIXELSHIFTEPERISO_TOOLTIP"));
+ pixelShiftEperIso->setAdjusterListener (this);
+
+ if (pixelShiftEperIso->delay < options.adjusterMaxDelay) {
+ pixelShiftEperIso->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftEperIso->show();
+ pixelShiftOptions->pack_start(*pixelShiftEperIso);
+
+
+ pixelShiftMedian = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTMEDIAN")));
+ pixelShiftMedian->set_tooltip_text (M("TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP"));
+ pixelShiftOptions->pack_start(*pixelShiftMedian);
+
+
+#ifdef PIXELSHIFTDEV
+ pixelShiftMedian3 = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTMEDIAN3")));
+ pixelShiftMedian3->set_tooltip_text (M("TP_RAW_PIXELSHIFTMEDIAN3_TOOLTIP"));
+ pixelShiftOptions->pack_start(*pixelShiftMedian3);
+
+ pixelShiftNonGreenCross2 = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTNONGREENCROSS2")));
+ pixelShiftOptions->pack_start(*pixelShiftNonGreenCross2);
+
+ pixelShiftNonGreenAmaze = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTNONGREENAMAZE")));
+ pixelShiftOptions->pack_start(*pixelShiftNonGreenAmaze);
+
+ pixelShiftNonGreenHorizontal = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTNONGREENHORIZONTAL")));
+ pixelShiftOptions->pack_start(*pixelShiftNonGreenHorizontal);
+
+ pixelShiftNonGreenVertical = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTNONGREENVERTICAL")));
+ pixelShiftOptions->pack_start(*pixelShiftNonGreenVertical);
+
+ pixelShiftExp0 = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTEXP0")));
+ pixelShiftOptions->pack_start(*pixelShiftExp0);
+#endif
+ pixelShiftLmmse = Gtk::manage (new MyCheckButton(M("TP_RAW_PIXELSHIFTLMMSE")));
+ pixelShiftLmmse->set_tooltip_text (M("TP_RAW_PIXELSHIFTLMMSE_TOOLTIP"));
+ pixelShiftOptions->pack_start(*pixelShiftLmmse);
+
+#ifdef PIXELSHIFTDEV
+ pixelShiftMotion = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTMOTION"), 0, 100, 1, 70));
+ pixelShiftMotion->setAdjusterListener (this);
+ pixelShiftMotion->set_tooltip_text (M("TP_RAW_PIXELSHIFTMOTION_TOOLTIP"));
+
+ if (pixelShiftMotion->delay < options.adjusterMaxDelay) {
+ pixelShiftMotion->delay = options.adjusterMaxDelay;
+ }
+ pixelShiftMotion->show();
+ pixelShiftOptions->pack_start(*pixelShiftMotion);
+
+ Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ());
+ hb2->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_PIXELSHIFTMOTIONCORRECTION") + ": ")), Gtk::PACK_SHRINK, 0);
+ pixelShiftMotionCorrection = Gtk::manage (new MyComboBoxText ());
+ pixelShiftMotionCorrection->append("1x1");
+ pixelShiftMotionCorrection->append("1x2");
+ pixelShiftMotionCorrection->append("3x3");
+ pixelShiftMotionCorrection->append("5x5");
+ pixelShiftMotionCorrection->append("7x7");
+ pixelShiftMotionCorrection->append("3x3 new");
+ pixelShiftMotionCorrection->set_active(0);
+ pixelShiftMotionCorrection->show();
+ hb2->pack_start(*pixelShiftMotionCorrection);
+ pixelShiftOptions->pack_start(*hb2);
+ pixelShiftStddevFactorGreen = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSTDDEVFACTORGREEN"), 2, 8, 0.1, 5));
+ pixelShiftStddevFactorGreen->setAdjusterListener (this);
+
+ if (pixelShiftStddevFactorGreen->delay < options.adjusterMaxDelay) {
+ pixelShiftStddevFactorGreen->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftStddevFactorGreen->show();
+ pixelShiftOptions->pack_start(*pixelShiftStddevFactorGreen);
+
+ pixelShiftStddevFactorRed = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSTDDEVFACTORRED"), 1, 8, 0.1, 5));
+ pixelShiftStddevFactorRed->setAdjusterListener (this);
+
+ if (pixelShiftStddevFactorRed->delay < options.adjusterMaxDelay) {
+ pixelShiftStddevFactorRed->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftStddevFactorRed->show();
+ pixelShiftOptions->pack_start(*pixelShiftStddevFactorRed);
+
+ pixelShiftStddevFactorBlue = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTSTDDEVFACTORBLUE"), 1, 8, 0.1, 5));
+ pixelShiftStddevFactorBlue->setAdjusterListener (this);
+
+ if (pixelShiftStddevFactorBlue->delay < options.adjusterMaxDelay) {
+ pixelShiftStddevFactorBlue->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftStddevFactorBlue->show();
+ pixelShiftOptions->pack_start(*pixelShiftStddevFactorBlue);
+#endif
+
+#ifdef PIXELSHIFTDEV
+ pixelShiftNreadIso = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTNREADISO"), -2.0, 2.0, 0.05, 0.0));
+ pixelShiftNreadIso->setAdjusterListener (this);
+
+ if (pixelShiftNreadIso->delay < options.adjusterMaxDelay) {
+ pixelShiftNreadIso->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftNreadIso->show();
+ pixelShiftOptions->pack_start(*pixelShiftNreadIso);
+
+
+ pixelShiftPrnu = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTPRNU"), 0.3, 2.0, 0.1, 1.0));
+ pixelShiftPrnu->setAdjusterListener (this);
+
+ if (pixelShiftPrnu->delay < options.adjusterMaxDelay) {
+ pixelShiftPrnu->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftPrnu->show();
+ pixelShiftOptions->pack_start(*pixelShiftPrnu);
+
+ pixelShiftSum = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTMASKTHRESHOLD"), 1.0, 8.0, 0.1, 3.0));
+ pixelShiftSum->setAdjusterListener (this);
+
+ if (pixelShiftSum->delay < options.adjusterMaxDelay) {
+ pixelShiftSum->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftSum->show();
+ pixelShiftOptions->pack_start(*pixelShiftSum);
+
+ pixelShiftRedBlueWeight = Gtk::manage (new Adjuster (M("TP_RAW_PIXELSHIFTREDBLUEWEIGHT"), 0.1, 1.0, 0.1, 0.7));
+ pixelShiftRedBlueWeight->setAdjusterListener (this);
+
+ if (pixelShiftRedBlueWeight->delay < options.adjusterMaxDelay) {
+ pixelShiftRedBlueWeight->delay = options.adjusterMaxDelay;
+ }
+
+ pixelShiftRedBlueWeight->show();
+ pixelShiftOptions->pack_start(*pixelShiftRedBlueWeight);
+#endif
+
+ pixelShiftFrame->pack_start(*pixelShiftOptions);
+ pixelShiftOptions->hide();
+
+ pack_start( *pixelShiftFrame, Gtk::PACK_SHRINK, 4);
+
+ method->connect(method->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::methodChanged) ));
+ imageNumber->connect(imageNumber->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::imageNumberChanged) ));
+ dcbEnhance->connect ( dcbEnhance->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::dcbEnhanceChanged), true));
+ pixelShiftMotionMethod->connect(pixelShiftMotionMethod->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::pixelShiftMotionMethodChanged) ));
+ pixelShiftShowMotion->connect(pixelShiftShowMotion->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftShowMotionChanged), true));
+ pixelShiftShowMotionMaskOnly->connect(pixelShiftShowMotionMaskOnly->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftShowMotionMaskOnlyChanged), true));
+ pixelShiftHoleFill->connect(pixelShiftHoleFill->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftHoleFillChanged), true));
+ pixelShiftMedian->connect(pixelShiftMedian->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftMedianChanged), true));
+ pixelShiftGreen->connect(pixelShiftGreen->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftGreenChanged), true));
+ pixelShiftBlur->connect(pixelShiftBlur->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftBlurChanged), true));
+ pixelShiftLmmse->connect(pixelShiftLmmse->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftLmmseChanged), true));
+ pixelShiftEqualBright->connect(pixelShiftEqualBright->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftEqualBrightChanged), true));
+ pixelShiftNonGreenCross->connect(pixelShiftNonGreenCross->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftNonGreenCrossChanged), true));
+#ifdef PIXELSHIFTDEV
+ pixelShiftMotionCorrection->connect(pixelShiftMotionCorrection->signal_changed().connect( sigc::mem_fun(*this, &BayerProcess::psMotionCorrectionChanged) ));
+ pixelShiftAutomatic->connect(pixelShiftAutomatic->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftAutomaticChanged), true));
+ pixelShiftNonGreenHorizontal->connect(pixelShiftNonGreenHorizontal->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftNonGreenHorizontalChanged), true));
+ pixelShiftNonGreenVertical->connect(pixelShiftNonGreenVertical->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftNonGreenVerticalChanged), true));
+ pixelShiftMedian3->connect(pixelShiftMedian3->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftMedian3Changed), true));
+ pixelShiftExp0->connect(pixelShiftExp0->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftExp0Changed), true));
+ pixelShiftNonGreenCross2->connect(pixelShiftNonGreenCross2->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftNonGreenCross2Changed), true));
+ pixelShiftNonGreenAmaze->connect(pixelShiftNonGreenAmaze->signal_toggled().connect ( sigc::mem_fun(*this, &BayerProcess::pixelShiftNonGreenAmazeChanged), true));
+#endif
}
void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited)
{
disableListener ();
- methodconn.block (true);
- dcbEnhconn.block (true);
+ method->block (true);
+ dcbEnhance->block (true);
+ imageNumber->block (true);
//allEnhconn.block (true);
method->set_active(procparams::RAWParams::BayerSensor::numMethods);
+ imageNumber->set_active(pp->raw.bayersensor.imageNum);
- for( size_t i = 0; i < procparams::RAWParams::BayerSensor::numMethods; i++)
+ for( size_t i = 0; i < procparams::RAWParams::BayerSensor::numMethods; i++) {
if( pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[i]) {
method->set_active(i);
- oldSelection = i;
+ oldMethod = i;
break;
}
+ }
- if(pedited ) {
+ if(pedited) {
ccSteps->setEditedState (pedited->raw.bayersensor.ccSteps ? Edited : UnEdited);
dcbIterations->setEditedState ( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited);
dcbEnhance->set_inconsistent(!pedited->raw.bayersensor.dcbEnhance);
- //allEnhance->set_inconsistent(!pedited->raw.bayersensor.allEnhance);
+ pixelShiftShowMotion->set_inconsistent(!pedited->raw.bayersensor.pixelshiftShowMotion);
+ pixelShiftShowMotionMaskOnly->set_inconsistent(!pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly);
+ pixelShiftHoleFill->set_inconsistent(!pedited->raw.bayersensor.pixelShiftHoleFill);
+ pixelShiftMedian->set_inconsistent(!pedited->raw.bayersensor.pixelShiftMedian);
+ pixelShiftGreen->set_inconsistent(!pedited->raw.bayersensor.pixelShiftGreen);
+ pixelShiftBlur->set_inconsistent(!pedited->raw.bayersensor.pixelShiftBlur);
+ pixelShiftSmooth->setEditedState ( pedited->raw.bayersensor.pixelShiftSmooth ? Edited : UnEdited);
+ pixelShiftLmmse->set_inconsistent(!pedited->raw.bayersensor.pixelShiftLmmse);
+ pixelShiftEqualBright->set_inconsistent(!pedited->raw.bayersensor.pixelShiftEqualBright);
+ pixelShiftNonGreenCross->set_inconsistent(!pedited->raw.bayersensor.pixelShiftNonGreenCross);
lmmseIterations->setEditedState ( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited);
+ pixelShiftEperIso->setEditedState ( pedited->raw.bayersensor.pixelShiftEperIso ? Edited : UnEdited);
+ pixelShiftSigma->setEditedState ( pedited->raw.bayersensor.pixelShiftSigma ? Edited : UnEdited);
+#ifdef PIXELSHIFTDEV
+ pixelShiftNreadIso->setEditedState ( pedited->raw.bayersensor.pixelShiftNreadIso ? Edited : UnEdited);
+ pixelShiftPrnu->setEditedState ( pedited->raw.bayersensor.pixelShiftPrnu ? Edited : UnEdited);
+ pixelShiftStddevFactorGreen->setEditedState ( pedited->raw.bayersensor.pixelShiftStddevFactorGreen ? Edited : UnEdited);
+ pixelShiftStddevFactorRed->setEditedState ( pedited->raw.bayersensor.pixelShiftStddevFactorRed ? Edited : UnEdited);
+ pixelShiftStddevFactorBlue->setEditedState ( pedited->raw.bayersensor.pixelShiftStddevFactorBlue ? Edited : UnEdited);
+ pixelShiftSum->setEditedState ( pedited->raw.bayersensor.pixelShiftSum ? Edited : UnEdited);
+ pixelShiftAutomatic->set_inconsistent(!pedited->raw.bayersensor.pixelShiftAutomatic);
+ pixelShiftNonGreenHorizontal->set_inconsistent(!pedited->raw.bayersensor.pixelShiftNonGreenHorizontal);
+ pixelShiftNonGreenVertical->set_inconsistent(!pedited->raw.bayersensor.pixelShiftNonGreenVertical);
+ pixelShiftMedian3->set_inconsistent(!pedited->raw.bayersensor.pixelShiftMedian3);
+ pixelShiftExp0->set_inconsistent(!pedited->raw.bayersensor.pixelShiftExp0);
+ pixelShiftNonGreenCross2->set_inconsistent(!pedited->raw.bayersensor.pixelShiftNonGreenCross2);
+ pixelShiftNonGreenAmaze->set_inconsistent(!pedited->raw.bayersensor.pixelShiftNonGreenAmaze);
+ pixelShiftMotion->setEditedState ( pedited->raw.bayersensor.pixelShiftMotion ? Edited : UnEdited);
+ pixelShiftRedBlueWeight->setEditedState ( pedited->raw.bayersensor.pixelShiftRedBlueWeight ? Edited : UnEdited);
+#endif
- if( !pedited->raw.bayersensor.method ) {
+ if(!pedited->raw.bayersensor.method) {
method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name
}
+ if(!pedited->raw.bayersensor.imageNum) {
+ imageNumber->set_active_text(M("GENERAL_UNCHANGED"));
+ }
+#ifdef PIXELSHIFTDEV
+ if(!pedited->raw.bayersensor.pixelShiftMotionCorrection) {
+ pixelShiftMotionCorrection->set_active_text(M("GENERAL_UNCHANGED"));
+ }
+#endif
+ if(!pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod) {
+ pixelShiftMotionMethod->set_active_text(M("GENERAL_UNCHANGED"));
+ }
}
//allEnhance->set_active(pp->raw.bayersensor.all_enhance);
dcbIterations->setValue (pp->raw.bayersensor.dcb_iterations);
dcbEnhance->set_active(pp->raw.bayersensor.dcb_enhance);
+ pixelShiftShowMotion->set_active(pp->raw.bayersensor.pixelshiftShowMotion);
+ pixelShiftShowMotionMaskOnly->set_sensitive(pp->raw.bayersensor.pixelshiftShowMotion);
+ pixelShiftShowMotionMaskOnly->set_active(pp->raw.bayersensor.pixelshiftShowMotionMaskOnly);
+ pixelShiftHoleFill->set_active(pp->raw.bayersensor.pixelShiftHoleFill);
+ pixelShiftMedian->set_active(pp->raw.bayersensor.pixelShiftMedian);
+ pixelShiftGreen->set_active(pp->raw.bayersensor.pixelShiftGreen);
+ pixelShiftBlur->set_active(pp->raw.bayersensor.pixelShiftBlur);
+ pixelShiftSmooth->set_sensitive (pp->raw.bayersensor.pixelShiftBlur);
+ pixelShiftSmooth->setValue (pp->raw.bayersensor.pixelShiftSmoothFactor);
+ pixelShiftLmmse->set_active(pp->raw.bayersensor.pixelShiftLmmse);
+ pixelShiftEqualBright->set_active(pp->raw.bayersensor.pixelShiftEqualBright);
+ pixelShiftNonGreenCross->set_active(pp->raw.bayersensor.pixelShiftNonGreenCross);
ccSteps->setValue (pp->raw.bayersensor.ccSteps);
-
- if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::dcb] ||
- method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) {
- dcbOptions->show();
- } else {
- dcbOptions->hide();
- }
-
lmmseIterations->setValue (pp->raw.bayersensor.lmmse_iterations);
+ pixelShiftMotionMethod->set_active ((int)pp->raw.bayersensor.pixelShiftMotionCorrectionMethod);
+ pixelShiftEperIso->setValue (pp->raw.bayersensor.pixelShiftEperIso);
+ pixelShiftSigma->setValue (pp->raw.bayersensor.pixelShiftSigma);
+ pixelShiftSigma->set_sensitive (pp->raw.bayersensor.pixelShiftBlur);
+#ifdef PIXELSHIFTDEV
+ pixelShiftStddevFactorGreen->setValue (pp->raw.bayersensor.pixelShiftStddevFactorGreen);
+ pixelShiftStddevFactorRed->setValue (pp->raw.bayersensor.pixelShiftStddevFactorRed);
+ pixelShiftStddevFactorBlue->setValue (pp->raw.bayersensor.pixelShiftStddevFactorBlue);
+ pixelShiftSum->setValue (pp->raw.bayersensor.pixelShiftSum);
+ pixelShiftMedian3->set_active(pp->raw.bayersensor.pixelShiftMedian3);
+ pixelShiftMedian3->set_sensitive(pixelShiftMedian->get_active());
+ pixelShiftAutomatic->set_active(pp->raw.bayersensor.pixelShiftAutomatic);
+ pixelShiftNonGreenHorizontal->set_active(pp->raw.bayersensor.pixelShiftNonGreenHorizontal);
+ pixelShiftNonGreenVertical->set_active(pp->raw.bayersensor.pixelShiftNonGreenVertical);
+ pixelShiftExp0->set_active(pp->raw.bayersensor.pixelShiftExp0);
+ pixelShiftNonGreenCross2->set_active(pp->raw.bayersensor.pixelShiftNonGreenCross2);
+ pixelShiftNonGreenAmaze->set_active(pp->raw.bayersensor.pixelShiftNonGreenAmaze);
+ pixelShiftMotion->setValue (pp->raw.bayersensor.pixelShiftMotion);
+ pixelShiftMotionCorrection->set_active ((int)pp->raw.bayersensor.pixelShiftMotionCorrection);
+ pixelShiftHoleFill->set_sensitive(pixelShiftAutomatic->get_active () && pixelShiftMotionCorrection->get_active_row_number() == 5);
+ pixelShiftBlur->set_sensitive(pixelShiftAutomatic->get_active () && pixelShiftMotionCorrection->get_active_row_number() == 5);
+ pixelShiftSmooth->set_sensitive(pixelShiftAutomatic->get_active () && pixelShiftMotionCorrection->get_active_row_number() == 5 && pixelShiftBlur->get_active());
+ pixelShiftNreadIso->setValue (pp->raw.bayersensor.pixelShiftNreadIso);
+ pixelShiftPrnu->setValue (pp->raw.bayersensor.pixelShiftPrnu);
+ pixelShiftRedBlueWeight->setValue (pp->raw.bayersensor.pixelShiftRedBlueWeight);
+#endif
+ if (!batchMode) {
+ if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::dcb] ||
+ method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) {
+ dcbOptions->show();
+ } else {
+ dcbOptions->hide();
+ }
+ if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::lmmse] ||
+ method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) {
+ lmmseOptions->show();
+ } else {
+ lmmseOptions->hide();
+ }
+ if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::pixelshift] ||
+ method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) {
+ if(pp->raw.bayersensor.pixelShiftMotionCorrectionMethod == RAWParams::BayerSensor::Custom) {
+ pixelShiftOptions->show();
+ } else {
+ pixelShiftOptions->hide();
+ }
+ pixelShiftFrame->show();
+ } else {
+ pixelShiftFrame->hide();
+ }
- if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::lmmse] ||
- method->get_active_row_number() == procparams::RAWParams::BayerSensor::numMethods) {
- lmmseOptions->show();
- } else {
- lmmseOptions->hide();
+ // Flase color suppression is applied to all demozaicing method, so don't hide anything
+ /*if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::eahd] ||
+ pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::hphd] ||
+ pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::vng4])
+ ccSteps->show();
+ else
+ ccSteps->hide();*/
}
- // Flase color suppression is applied to all demozaicing method, so don't hide anything
- /*if (pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::eahd] ||
- pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::hphd] ||
- pp->raw.bayersensor.method == procparams::RAWParams::BayerSensor::methodstring[procparams::RAWParams::BayerSensor::vng4])
- ccSteps->show();
- else
- ccSteps->hide();*/
-
- lastDCBen = pp->raw.bayersensor.dcb_enhance;
+ dcbEnhance->setLastActive(pp->raw.bayersensor.dcb_enhance);
+ pixelShiftShowMotion->setLastActive(pp->raw.bayersensor.pixelshiftShowMotion);
+ pixelShiftShowMotionMaskOnly->setLastActive(pp->raw.bayersensor.pixelshiftShowMotionMaskOnly);
+ pixelShiftNonGreenCross->setLastActive(pp->raw.bayersensor.pixelShiftNonGreenCross);
+ pixelShiftGreen->setLastActive(pp->raw.bayersensor.pixelShiftGreen);
+ pixelShiftBlur->setLastActive(pp->raw.bayersensor.pixelShiftBlur);
+ pixelShiftHoleFill->setLastActive(pp->raw.bayersensor.pixelShiftHoleFill);
+ pixelShiftMedian->setLastActive(pp->raw.bayersensor.pixelShiftMedian);
+ pixelShiftLmmse->setLastActive(pp->raw.bayersensor.pixelShiftLmmse);
+ pixelShiftEqualBright->setLastActive(pp->raw.bayersensor.pixelShiftEqualBright);
+#ifdef PIXELSHIFTDEV
+ pixelShiftMedian3->setLastActive(pp->raw.bayersensor.pixelShiftMedian3);
+ pixelShiftAutomatic->setLastActive(pp->raw.bayersensor.pixelShiftAutomatic);
+ pixelShiftNonGreenHorizontal->setLastActive(pp->raw.bayersensor.pixelShiftNonGreenHorizontal);
+ pixelShiftNonGreenVertical->setLastActive(pp->raw.bayersensor.pixelShiftNonGreenVertical);
+ pixelShiftNonGreenCross2->setLastActive(pp->raw.bayersensor.pixelShiftNonGreenCross2);
+ pixelShiftNonGreenAmaze->setLastActive(pp->raw.bayersensor.pixelShiftNonGreenAmaze);
+ pixelShiftExp0->setLastActive(pp->raw.bayersensor.pixelShiftExp0);
+#endif
+
//lastALLen = pp->raw.bayersensor.all_enhance;
- methodconn.block (false);
- dcbEnhconn.block (false);
+ method->block (false);
+#ifdef PIXELSHIFTDEV
+ pixelShiftMotionCorrection->block (false);
+#endif
+ imageNumber->block (false);
+ dcbEnhance->block (false);
//allEnhconn.block (false);
enableListener ();
@@ -165,21 +519,88 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe
pp->raw.bayersensor.dcb_enhance = dcbEnhance->get_active();
//pp->raw.bayersensor.all_enhance = allEnhance->get_active();
pp->raw.bayersensor.lmmse_iterations = lmmseIterations->getIntValue();
+ pp->raw.bayersensor.pixelShiftMotionCorrectionMethod = (RAWParams::BayerSensor::ePSMotionCorrectionMethod)pixelShiftMotionMethod->get_active_row_number();
+ pp->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getValue();
+ pp->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getValue();
+ pp->raw.bayersensor.pixelshiftShowMotion = pixelShiftShowMotion->get_active();
+ pp->raw.bayersensor.pixelshiftShowMotionMaskOnly = pixelShiftShowMotionMaskOnly->get_active();
+ pp->raw.bayersensor.pixelShiftHoleFill = pixelShiftHoleFill->get_active();
+ pp->raw.bayersensor.pixelShiftMedian = pixelShiftMedian->get_active();
+ pp->raw.bayersensor.pixelShiftGreen = pixelShiftGreen->get_active();
+ pp->raw.bayersensor.pixelShiftBlur = pixelShiftBlur->get_active();
+ pp->raw.bayersensor.pixelShiftSmoothFactor = pixelShiftSmooth->getValue();
+ pp->raw.bayersensor.pixelShiftLmmse = pixelShiftLmmse->get_active();
+ pp->raw.bayersensor.pixelShiftEqualBright = pixelShiftEqualBright->get_active();
+ pp->raw.bayersensor.pixelShiftNonGreenCross = pixelShiftNonGreenCross->get_active();
+#ifdef PIXELSHIFTDEV
+ pp->raw.bayersensor.pixelShiftStddevFactorGreen = pixelShiftStddevFactorGreen->getValue();
+ pp->raw.bayersensor.pixelShiftStddevFactorRed = pixelShiftStddevFactorRed->getValue();
+ pp->raw.bayersensor.pixelShiftStddevFactorBlue = pixelShiftStddevFactorBlue->getValue();
+ pp->raw.bayersensor.pixelShiftSum = pixelShiftSum->getValue();
+ pp->raw.bayersensor.pixelShiftMedian3 = pixelShiftMedian3->get_active();
+ pp->raw.bayersensor.pixelShiftMotion = pixelShiftMotion->getIntValue();
+ pp->raw.bayersensor.pixelShiftMotionCorrection = (RAWParams::BayerSensor::ePSMotionCorrection)pixelShiftMotionCorrection->get_active_row_number();
+ pp->raw.bayersensor.pixelShiftAutomatic = pixelShiftAutomatic->get_active();
+ pp->raw.bayersensor.pixelShiftNonGreenHorizontal = pixelShiftNonGreenHorizontal->get_active();
+ pp->raw.bayersensor.pixelShiftNonGreenVertical = pixelShiftNonGreenVertical->get_active();
+ pp->raw.bayersensor.pixelShiftExp0 = pixelShiftExp0->get_active();
+ pp->raw.bayersensor.pixelShiftNonGreenCross2 = pixelShiftNonGreenCross2->get_active();
+ pp->raw.bayersensor.pixelShiftNonGreenAmaze = pixelShiftNonGreenAmaze->get_active();
+ pp->raw.bayersensor.pixelShiftNreadIso = pixelShiftNreadIso->getValue();
+ pp->raw.bayersensor.pixelShiftPrnu = pixelShiftPrnu->getValue();
+ pp->raw.bayersensor.pixelShiftRedBlueWeight = pixelShiftRedBlueWeight->getValue();
+#endif
int currentRow = method->get_active_row_number();
-
if( currentRow >= 0 && currentRow < procparams::RAWParams::BayerSensor::numMethods) {
pp->raw.bayersensor.method = procparams::RAWParams::BayerSensor::methodstring[currentRow];
}
+ currentRow = imageNumber->get_active_row_number();
+ if (currentRow < 4) {
+ pp->raw.bayersensor.imageNum = currentRow;
+ }
+
+
if (pedited) {
pedited->raw.bayersensor.ccSteps = ccSteps->getEditedState ();
pedited->raw.bayersensor.method = method->get_active_row_number() != procparams::RAWParams::BayerSensor::numMethods;
+ pedited->raw.bayersensor.imageNum = imageNumber->get_active_text() != M("GENERAL_UNCHANGED");
pedited->raw.bayersensor.dcbIterations = dcbIterations->getEditedState ();
pedited->raw.bayersensor.dcbEnhance = !dcbEnhance->get_inconsistent();
//pedited->raw.bayersensor.allEnhance = !allEnhance->get_inconsistent();
pedited->raw.bayersensor.lmmseIterations = lmmseIterations->getEditedState ();
-
+ pedited->raw.bayersensor.pixelShiftMotionCorrectionMethod = pixelShiftMotionMethod->get_active_text() != M("GENERAL_UNCHANGED");
+ pedited->raw.bayersensor.pixelShiftEperIso = pixelShiftEperIso->getEditedState ();
+ pedited->raw.bayersensor.pixelShiftSigma = pixelShiftSigma->getEditedState ();
+ pedited->raw.bayersensor.pixelshiftShowMotion = !pixelShiftShowMotion->get_inconsistent();
+ pedited->raw.bayersensor.pixelshiftShowMotionMaskOnly = !pixelShiftShowMotionMaskOnly->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftHoleFill = !pixelShiftHoleFill->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftMedian = !pixelShiftMedian->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftGreen = !pixelShiftGreen->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftBlur = !pixelShiftBlur->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftSmooth = pixelShiftSmooth->getEditedState();
+ pedited->raw.bayersensor.pixelShiftLmmse = !pixelShiftLmmse->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftEqualBright = !pixelShiftEqualBright->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftNonGreenCross = !pixelShiftNonGreenCross->get_inconsistent();
+#ifdef PIXELSHIFTDEV
+ pedited->raw.bayersensor.pixelShiftStddevFactorGreen = pixelShiftStddevFactorGreen->getEditedState ();
+ pedited->raw.bayersensor.pixelShiftStddevFactorRed = pixelShiftStddevFactorRed->getEditedState ();
+ pedited->raw.bayersensor.pixelShiftStddevFactorBlue = pixelShiftStddevFactorBlue->getEditedState ();
+ pedited->raw.bayersensor.pixelShiftSum = pixelShiftSum->getEditedState ();
+ pedited->raw.bayersensor.pixelShiftMedian3 = !pixelShiftMedian3->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftMotion = pixelShiftMotion->getEditedState ();
+ pedited->raw.bayersensor.pixelShiftMotionCorrection = pixelShiftMotionCorrection->get_active_text() != M("GENERAL_UNCHANGED");
+ pedited->raw.bayersensor.pixelShiftAutomatic = !pixelShiftAutomatic->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftNonGreenHorizontal = !pixelShiftNonGreenHorizontal->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftNonGreenVertical = !pixelShiftNonGreenVertical->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftExp0 = !pixelShiftExp0->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftNonGreenCross2 = !pixelShiftNonGreenCross2->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftNonGreenAmaze = !pixelShiftNonGreenAmaze->get_inconsistent();
+ pedited->raw.bayersensor.pixelShiftNreadIso = pixelShiftNreadIso->getEditedState ();
+ pedited->raw.bayersensor.pixelShiftPrnu = pixelShiftPrnu->getEditedState ();
+ pedited->raw.bayersensor.pixelShiftRedBlueWeight = pixelShiftRedBlueWeight->getEditedState ();
+#endif
}
}
@@ -187,27 +608,84 @@ void BayerProcess::setBatchMode(bool batchMode)
{
method->append (M("GENERAL_UNCHANGED"));
method->set_active(procparams::RAWParams::BayerSensor::numMethods); // No name
+#ifdef PIXELSHIFTDEV
+ pixelShiftMotionCorrection->append (M("GENERAL_UNCHANGED"));
+ pixelShiftMotionCorrection->set_active (4);
+#endif
+ pixelShiftMotionMethod->append (M("GENERAL_UNCHANGED"));
+ pixelShiftMotionMethod->set_active (4);
+ imageNumber->append (M("GENERAL_UNCHANGED"));
+ imageNumber->set_active(4);
dcbOptions->hide();
lmmseOptions->hide();
+ pixelShiftOptions->hide();
ToolPanel::setBatchMode (batchMode);
ccSteps->showEditedCB ();
dcbIterations->showEditedCB ();
lmmseIterations->showEditedCB ();
+#ifdef PIXELSHIFTDEV
+ pixelShiftMotion->showEditedCB ();
+ pixelShiftSum->showEditedCB ();
+ pixelShiftStddevFactorGreen->showEditedCB ();
+ pixelShiftStddevFactorRed->showEditedCB ();
+ pixelShiftStddevFactorBlue->showEditedCB ();
+ pixelShiftNreadIso->showEditedCB ();
+ pixelShiftPrnu->showEditedCB ();
+ pixelShiftRedBlueWeight->showEditedCB ();
+#endif
+ pixelShiftEperIso->showEditedCB ();
+ pixelShiftSigma->showEditedCB ();
}
void BayerProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited)
{
dcbIterations->setDefault( defParams->raw.bayersensor.dcb_iterations);
lmmseIterations->setDefault( defParams->raw.bayersensor.lmmse_iterations);
+#ifdef PIXELSHIFTDEV
+ pixelShiftMotion->setDefault( defParams->raw.bayersensor.pixelShiftMotion);
+ pixelShiftSum->setDefault( defParams->raw.bayersensor.pixelShiftSum);
+ pixelShiftStddevFactorGreen->setDefault( defParams->raw.bayersensor.pixelShiftStddevFactorGreen);
+ pixelShiftStddevFactorRed->setDefault( defParams->raw.bayersensor.pixelShiftStddevFactorRed);
+ pixelShiftStddevFactorBlue->setDefault( defParams->raw.bayersensor.pixelShiftStddevFactorBlue);
+ pixelShiftNreadIso->setDefault( defParams->raw.bayersensor.pixelShiftNreadIso);
+ pixelShiftPrnu->setDefault( defParams->raw.bayersensor.pixelShiftPrnu);
+ pixelShiftRedBlueWeight->setDefault( defParams->raw.bayersensor.pixelShiftRedBlueWeight);
+#endif
+ pixelShiftEperIso->setDefault( defParams->raw.bayersensor.pixelShiftEperIso);
+ pixelShiftSigma->setDefault( defParams->raw.bayersensor.pixelShiftSigma);
ccSteps->setDefault (defParams->raw.bayersensor.ccSteps);
if (pedited) {
dcbIterations->setDefaultEditedState( pedited->raw.bayersensor.dcbIterations ? Edited : UnEdited);
lmmseIterations->setDefaultEditedState( pedited->raw.bayersensor.lmmseIterations ? Edited : UnEdited);
+#ifdef PIXELSHIFTDEV
+ pixelShiftMotion->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftMotion ? Edited : UnEdited);
+ pixelShiftSum->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftSum ? Edited : UnEdited);
+ pixelShiftStddevFactorGreen->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftStddevFactorGreen ? Edited : UnEdited);
+ pixelShiftStddevFactorRed->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftStddevFactorRed ? Edited : UnEdited);
+ pixelShiftStddevFactorBlue->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftStddevFactorBlue ? Edited : UnEdited);
+ pixelShiftNreadIso->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftNreadIso ? Edited : UnEdited);
+ pixelShiftPrnu->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftPrnu ? Edited : UnEdited);
+ pixelShiftRedBlueWeight->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftRedBlueWeight ? Edited : UnEdited);
+#endif
+ pixelShiftEperIso->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftEperIso ? Edited : UnEdited);
+ pixelShiftSigma->setDefaultEditedState( pedited->raw.bayersensor.pixelShiftSigma ? Edited : UnEdited);
ccSteps->setDefaultEditedState(pedited->raw.bayersensor.ccSteps ? Edited : UnEdited);
} else {
dcbIterations->setDefaultEditedState( Irrelevant );
lmmseIterations->setDefaultEditedState( Irrelevant );
+#ifdef PIXELSHIFTDEV
+ pixelShiftMotion->setDefaultEditedState( Irrelevant );
+ pixelShiftSum->setDefaultEditedState( Irrelevant );
+ pixelShiftStddevFactorGreen->setDefaultEditedState( Irrelevant );
+ pixelShiftStddevFactorRed->setDefaultEditedState( Irrelevant );
+ pixelShiftStddevFactorBlue->setDefaultEditedState( Irrelevant );
+ pixelShiftNreadIso->setDefaultEditedState( Irrelevant );
+ pixelShiftPrnu->setDefaultEditedState( Irrelevant );
+ pixelShiftRedBlueWeight->setDefaultEditedState( Irrelevant );
+#endif
+ pixelShiftEperIso->setDefaultEditedState( Irrelevant );
+ pixelShiftSigma->setDefaultEditedState( Irrelevant );
ccSteps->setDefaultEditedState(Irrelevant );
}
}
@@ -221,10 +699,52 @@ void BayerProcess::adjusterChanged (Adjuster* a, double newval)
listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() );
} else if (a == lmmseIterations) {
listener->panelChanged (EvDemosaicLMMSEIter, a->getTextValue() );
+#ifdef PIXELSHIFTDEV
+ } else if (a == pixelShiftMotion) {
+ listener->panelChanged (EvPixelShiftMotion, a->getTextValue() );
+ } else if (a == pixelShiftSum) {
+ listener->panelChanged (EvPixelShiftSum, a->getTextValue() );
+ } else if (a == pixelShiftStddevFactorGreen) {
+ listener->panelChanged (EvPixelShiftStddevFactorGreen, a->getTextValue() );
+ } else if (a == pixelShiftStddevFactorRed) {
+ listener->panelChanged (EvPixelShiftStddevFactorRed, a->getTextValue() );
+ } else if (a == pixelShiftStddevFactorBlue) {
+ listener->panelChanged (EvPixelShiftStddevFactorBlue, a->getTextValue() );
+ } else if (a == pixelShiftNreadIso) {
+ listener->panelChanged (EvPixelShiftNreadIso, a->getTextValue() );
+ } else if (a == pixelShiftPrnu) {
+ listener->panelChanged (EvPixelShiftPrnu, a->getTextValue() );
+ } else if (a == pixelShiftRedBlueWeight) {
+ listener->panelChanged (EvPixelShiftRedBlueWeight, a->getTextValue() );
+#endif
+ } else if (a == pixelShiftEperIso) {
+ listener->panelChanged (EvPixelShiftEperIso, a->getTextValue() );
+ } else if (a == pixelShiftSigma) {
+ listener->panelChanged (EvPixelShiftSigma, a->getTextValue() );
+ } else if (a == pixelShiftSmooth) {
+ listener->panelChanged (EvPixelShiftSmooth, a->getTextValue() );
}
}
}
+#ifdef PIXELSHIFTDEV
+void BayerProcess::psMotionCorrectionChanged ()
+{
+ if(pixelShiftMotionCorrection->get_active_row_number() == 5) {
+ pixelShiftBlur->set_sensitive(true);
+ pixelShiftHoleFill->set_sensitive(true);
+ pixelShiftSmooth->set_sensitive(pixelShiftBlur->get_active());
+ } else {
+ pixelShiftBlur->set_sensitive(false);
+ pixelShiftHoleFill->set_sensitive(false);
+ pixelShiftSmooth->set_sensitive(false);
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftMotionCorrection, pixelShiftMotionCorrection->get_active_text());
+ }
+}
+#endif
void BayerProcess::methodChanged ()
{
int curSelection = method->get_active_row_number();
@@ -241,37 +761,55 @@ void BayerProcess::methodChanged ()
lmmseOptions->hide();
}
+ if ( curSelection == procparams::RAWParams::BayerSensor::pixelshift) {
+ if(pixelShiftMotionMethod->get_active_row_number() == 2) {
+ pixelShiftOptions->show();
+ } else {
+ pixelShiftOptions->hide();
+ }
+ pixelShiftFrame->show();
+ } else {
+ pixelShiftFrame->hide();
+ }
+
Glib::ustring methodName = "";
bool ppreq = false;
if( curSelection >= 0 && curSelection < procparams::RAWParams::BayerSensor::numMethods) {
methodName = procparams::RAWParams::BayerSensor::methodstring[curSelection];
- if (curSelection == procparams::RAWParams::BayerSensor::mono || oldSelection == procparams::RAWParams::BayerSensor::mono) {
+ if (curSelection == procparams::RAWParams::BayerSensor::mono || oldMethod == procparams::RAWParams::BayerSensor::mono) {
ppreq = true;
}
}
- oldSelection = curSelection;
+ oldMethod = curSelection;
if (listener) {
listener->panelChanged (ppreq ? EvDemosaicMethodPreProc : EvDemosaicMethod, methodName);
}
}
+void BayerProcess::imageNumberChanged ()
+{
+ if (listener) {
+ listener->panelChanged (EvRawImageNum, imageNumber->get_active_text());
+ }
+}
+
void BayerProcess::dcbEnhanceChanged ()
{
if (batchMode) {
if (dcbEnhance->get_inconsistent()) {
dcbEnhance->set_inconsistent (false);
- dcbEnhconn.block (true);
+ dcbEnhance->block (true);
dcbEnhance->set_active (false);
- dcbEnhconn.block (false);
- } else if (lastDCBen) {
+ dcbEnhance->block (false);
+ } else if (dcbEnhance->getLastActive()) {
dcbEnhance->set_inconsistent (true);
}
- lastDCBen = dcbEnhance->get_active ();
+ dcbEnhance->setLastActive();
}
if (listener) {
@@ -279,20 +817,370 @@ void BayerProcess::dcbEnhanceChanged ()
}
}
-/*void BayerProcess::allEnhanceChanged ()
+void BayerProcess::pixelShiftMotionMethodChanged ()
+{
+ if(pixelShiftMotionMethod->get_active_row_number() == 0) {
+ pixelShiftOptions->hide();
+ pixelShiftShowMotion->hide();
+ pixelShiftShowMotionMaskOnly->hide();
+ } else if(pixelShiftMotionMethod->get_active_row_number() == 2) {
+ pixelShiftOptions->show();
+ pixelShiftShowMotion->show();
+ pixelShiftShowMotionMaskOnly->show();
+ } else {
+ pixelShiftOptions->hide();
+ pixelShiftShowMotion->show();
+ pixelShiftShowMotionMaskOnly->show();
+ }
+ if (listener) {
+ listener->panelChanged (EvPixelShiftMotionMethod, pixelShiftMotionMethod->get_active_text());
+ }
+}
+
+void BayerProcess::pixelShiftShowMotionChanged ()
{
if (batchMode) {
- if (allEnhance->get_inconsistent()) {
- allEnhance->set_inconsistent (false);
- allEnhconn.block (true);
- allEnhance->set_active (false);
- allEnhconn.block (false);
+ if (pixelShiftShowMotion->get_inconsistent()) {
+ pixelShiftShowMotion->set_inconsistent (false);
+ pixelShiftShowMotion->block (true);
+ pixelShiftShowMotion->set_active (false);
+ pixelShiftShowMotion->block (false);
+ } else if (pixelShiftShowMotion->getLastActive()) {
+ pixelShiftShowMotion->set_inconsistent (true);
}
- else if (lastALLen)
- allEnhance->set_inconsistent (true);
- lastALLen = allEnhance->get_active ();
+ pixelShiftShowMotion->setLastActive();
}
- if (listener)
- listener->panelChanged (EvDemosaicALLEnhanced, allEnhance->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED"));
-}*/
+ pixelShiftShowMotionMaskOnly->set_sensitive(pixelShiftShowMotion->get_active ());
+ if (listener) {
+ listener->panelChanged (EvPixelshiftShowMotion, pixelShiftShowMotion->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+void BayerProcess::pixelShiftShowMotionMaskOnlyChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftShowMotionMaskOnly->get_inconsistent()) {
+ pixelShiftShowMotionMaskOnly->set_inconsistent (false);
+ pixelShiftShowMotionMaskOnly->block (true);
+ pixelShiftShowMotionMaskOnly->set_active (false);
+ pixelShiftShowMotionMaskOnly->block (false);
+ } else if (pixelShiftShowMotionMaskOnly->getLastActive()) {
+ pixelShiftShowMotionMaskOnly->set_inconsistent (true);
+ }
+
+ pixelShiftShowMotionMaskOnly->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelshiftShowMotionMaskOnly, pixelShiftShowMotionMaskOnly->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+#ifdef PIXELSHIFTDEV
+void BayerProcess::pixelShiftAutomaticChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftAutomatic->get_inconsistent()) {
+ pixelShiftAutomatic->set_inconsistent (false);
+ pixelShiftAutomatic->block (true);
+ pixelShiftAutomatic->set_active (false);
+ pixelShiftAutomatic->block (false);
+ } else if (pixelShiftAutomatic->getLastActive()) {
+ pixelShiftAutomatic->set_inconsistent (true);
+ }
+
+ pixelShiftAutomatic->setLastActive();
+ }
+ pixelShiftMotion->set_sensitive(!pixelShiftAutomatic->get_active ());
+ pixelShiftEperIso->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftNreadIso->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftPrnu->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftSigma->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftSum->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftRedBlueWeight->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftStddevFactorGreen->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftStddevFactorRed->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftStddevFactorBlue->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftNonGreenHorizontal->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftNonGreenVertical->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftHoleFill->set_sensitive(pixelShiftAutomatic->get_active () && pixelShiftMotionCorrection->get_active_row_number() == 5);
+ pixelShiftMedian3->set_sensitive(pixelShiftAutomatic->get_active () && pixelShiftMedian->get_active());
+ pixelShiftGreen->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftBlur->set_sensitive(pixelShiftAutomatic->get_active () && pixelShiftMotionCorrection->get_active_row_number() == 5);
+ pixelShiftSmooth->set_sensitive(pixelShiftAutomatic->get_active () && pixelShiftMotionCorrection->get_active_row_number() == 5 && pixelShiftBlur->get_active());
+ pixelShiftExp0->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftNonGreenCross->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftNonGreenCross2->set_sensitive(pixelShiftAutomatic->get_active ());
+ pixelShiftNonGreenAmaze->set_sensitive(pixelShiftAutomatic->get_active ());
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftAutomatic, pixelShiftAutomatic->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+void BayerProcess::pixelShiftNonGreenHorizontalChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftNonGreenHorizontal->get_inconsistent()) {
+ pixelShiftNonGreenHorizontal->set_inconsistent (false);
+ pixelShiftNonGreenHorizontal->block (true);
+ pixelShiftNonGreenHorizontal->set_active (false);
+ pixelShiftNonGreenHorizontal->block (false);
+ } else if (pixelShiftNonGreenHorizontal->getLastActive()) {
+ pixelShiftNonGreenHorizontal->set_inconsistent (true);
+ }
+
+ pixelShiftNonGreenHorizontal->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftNonGreenHorizontal, pixelShiftNonGreenHorizontal->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+void BayerProcess::pixelShiftNonGreenVerticalChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftNonGreenVertical->get_inconsistent()) {
+ pixelShiftNonGreenVertical->set_inconsistent (false);
+ pixelShiftNonGreenVertical->block (true);
+ pixelShiftNonGreenVertical->set_active (false);
+ pixelShiftNonGreenVertical->block (false);
+ } else if (pixelShiftNonGreenVertical->getLastActive()) {
+ pixelShiftNonGreenVertical->set_inconsistent (true);
+ }
+
+ pixelShiftNonGreenVertical->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftNonGreenVertical, pixelShiftNonGreenVertical->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+#endif
+
+void BayerProcess::pixelShiftHoleFillChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftHoleFill->get_inconsistent()) {
+ pixelShiftHoleFill->set_inconsistent (false);
+ pixelShiftHoleFill->block (true);
+ pixelShiftHoleFill->set_active (false);
+ pixelShiftHoleFill->block (false);
+ } else if (pixelShiftHoleFill->getLastActive()) {
+ pixelShiftHoleFill->set_inconsistent (true);
+ }
+
+ pixelShiftHoleFill->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftHoleFill, pixelShiftHoleFill->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+void BayerProcess::pixelShiftMedianChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftMedian->get_inconsistent()) {
+ pixelShiftMedian->set_inconsistent (false);
+ pixelShiftMedian->block (true);
+ pixelShiftMedian->set_active (false);
+ pixelShiftMedian->block (false);
+ } else if (pixelShiftMedian->getLastActive()) {
+ pixelShiftMedian->set_inconsistent (true);
+ }
+
+ pixelShiftMedian->setLastActive();
+ }
+#ifdef PIXELSHIFTDEV
+ pixelShiftMedian3->set_sensitive(pixelShiftMedian->get_active ());
+#endif
+ if (listener) {
+ listener->panelChanged (EvPixelShiftMedian, pixelShiftMedian->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+#ifdef PIXELSHIFTDEV
+void BayerProcess::pixelShiftMedian3Changed ()
+{
+ if (batchMode) {
+ if (pixelShiftMedian3->get_inconsistent()) {
+ pixelShiftMedian3->set_inconsistent (false);
+ pixelShiftMedian3->block (true);
+ pixelShiftMedian3->set_active (false);
+ pixelShiftMedian3->block (false);
+ } else if (pixelShiftMedian3->getLastActive()) {
+ pixelShiftMedian3->set_inconsistent (true);
+ }
+
+ pixelShiftMedian3->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftMedian3, pixelShiftMedian3->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+#endif
+void BayerProcess::pixelShiftGreenChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftGreen->get_inconsistent()) {
+ pixelShiftGreen->set_inconsistent (false);
+ pixelShiftGreen->block (true);
+ pixelShiftGreen->set_active (false);
+ pixelShiftGreen->block (false);
+ } else if (pixelShiftGreen->getLastActive()) {
+ pixelShiftGreen->set_inconsistent (true);
+ }
+
+ pixelShiftGreen->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftGreen, pixelShiftGreen->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+void BayerProcess::pixelShiftBlurChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftBlur->get_inconsistent()) {
+ pixelShiftBlur->set_inconsistent (false);
+ pixelShiftBlur->block (true);
+ pixelShiftBlur->set_active (false);
+ pixelShiftBlur->block (false);
+ } else if (pixelShiftBlur->getLastActive()) {
+ pixelShiftBlur->set_inconsistent (true);
+ }
+
+ pixelShiftBlur->setLastActive();
+ }
+
+ pixelShiftSmooth->set_sensitive(pixelShiftBlur->get_active ());
+ pixelShiftSigma->set_sensitive(pixelShiftBlur->get_active ());
+ if (listener) {
+ listener->panelChanged (EvPixelShiftBlur, pixelShiftBlur->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+#ifdef PIXELSHIFTDEV
+void BayerProcess::pixelShiftExp0Changed ()
+{
+ if (batchMode) {
+ if (pixelShiftExp0->get_inconsistent()) {
+ pixelShiftExp0->set_inconsistent (false);
+ pixelShiftExp0->block (true);
+ pixelShiftExp0->set_active (false);
+ pixelShiftExp0->block (false);
+ } else if (pixelShiftExp0->getLastActive()) {
+ pixelShiftExp0->set_inconsistent (true);
+ }
+
+ pixelShiftExp0->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftExp0, pixelShiftExp0->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+#endif
+void BayerProcess::pixelShiftLmmseChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftLmmse->get_inconsistent()) {
+ pixelShiftLmmse->set_inconsistent (false);
+ pixelShiftLmmse->block (true);
+ pixelShiftLmmse->set_active (false);
+ pixelShiftLmmse->block (false);
+ } else if (pixelShiftLmmse->getLastActive()) {
+ pixelShiftLmmse->set_inconsistent (true);
+ }
+
+ pixelShiftLmmse->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftLmmse, pixelShiftLmmse->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+void BayerProcess::pixelShiftEqualBrightChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftEqualBright->get_inconsistent()) {
+ pixelShiftEqualBright->set_inconsistent (false);
+ pixelShiftEqualBright->block (true);
+ pixelShiftEqualBright->set_active (false);
+ pixelShiftEqualBright->block (false);
+ } else if (pixelShiftEqualBright->getLastActive()) {
+ pixelShiftEqualBright->set_inconsistent (true);
+ }
+
+ pixelShiftEqualBright->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftEqualBright, pixelShiftEqualBright->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+void BayerProcess::pixelShiftNonGreenCrossChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftNonGreenCross->get_inconsistent()) {
+ pixelShiftNonGreenCross->set_inconsistent (false);
+ pixelShiftNonGreenCross->block (true);
+ pixelShiftNonGreenCross->set_active (false);
+ pixelShiftNonGreenCross->block (false);
+ } else if (pixelShiftNonGreenCross->getLastActive()) {
+ pixelShiftNonGreenCross->set_inconsistent (true);
+ }
+
+ pixelShiftNonGreenCross->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftNonGreenCross, pixelShiftNonGreenCross->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+#ifdef PIXELSHIFTDEV
+void BayerProcess::pixelShiftNonGreenCross2Changed ()
+{
+ if (batchMode) {
+ if (pixelShiftNonGreenCross2->get_inconsistent()) {
+ pixelShiftNonGreenCross2->set_inconsistent (false);
+ pixelShiftNonGreenCross2->block (true);
+ pixelShiftNonGreenCross2->set_active (false);
+ pixelShiftNonGreenCross2->block (false);
+ } else if (pixelShiftNonGreenCross2->getLastActive()) {
+ pixelShiftNonGreenCross2->set_inconsistent (true);
+ }
+
+ pixelShiftNonGreenCross2->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftGreenAmaze, pixelShiftNonGreenCross2->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+
+void BayerProcess::pixelShiftNonGreenAmazeChanged ()
+{
+ if (batchMode) {
+ if (pixelShiftNonGreenAmaze->get_inconsistent()) {
+ pixelShiftNonGreenAmaze->set_inconsistent (false);
+ pixelShiftNonGreenAmaze->block (true);
+ pixelShiftNonGreenAmaze->set_active (false);
+ pixelShiftNonGreenAmaze->block (false);
+ } else if (pixelShiftNonGreenAmaze->getLastActive()) {
+ pixelShiftNonGreenAmaze->set_inconsistent (true);
+ }
+
+ pixelShiftNonGreenAmaze->setLastActive();
+ }
+
+ if (listener) {
+ listener->panelChanged (EvPixelShiftNonGreenAmaze, pixelShiftNonGreenAmaze->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
+ }
+}
+#endif
\ No newline at end of file
diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h
index b78002ea3..463e8fb58 100644
--- a/rtgui/bayerprocess.h
+++ b/rtgui/bayerprocess.h
@@ -31,19 +31,48 @@ class BayerProcess : public ToolParamBlock, public AdjusterListener, public Fold
protected:
MyComboBoxText* method;
+ Gtk::HBox *imageNumberBox;
+ MyComboBoxText* imageNumber;
Adjuster* ccSteps;
Gtk::VBox *dcbOptions;
Adjuster* dcbIterations;
- Gtk::CheckButton* dcbEnhance;
- //Gtk::VBox *allOptions;
- //Gtk::CheckButton* allEnhance;
+ MyCheckButton* dcbEnhance;
Gtk::VBox *lmmseOptions;
Adjuster* lmmseIterations;
-
- bool lastDCBen;
- int oldSelection;
- //bool lastALLen;
- sigc::connection methodconn, dcbEnhconn; //,allEnhconn;
+ Gtk::VBox *pixelShiftFrame;
+ Gtk::VBox *pixelShiftOptions;
+ MyComboBoxText* pixelShiftMotionMethod;
+ MyCheckButton* pixelShiftShowMotion;
+ MyCheckButton* pixelShiftShowMotionMaskOnly;
+ MyCheckButton* pixelShiftNonGreenCross;
+ MyCheckButton* pixelShiftGreen;
+ MyCheckButton* pixelShiftBlur;
+ MyCheckButton* pixelShiftHoleFill;
+ MyCheckButton* pixelShiftMedian;
+ MyCheckButton* pixelShiftLmmse;
+ MyCheckButton* pixelShiftEqualBright;
+ Adjuster* pixelShiftSmooth;
+ Adjuster* pixelShiftEperIso;
+ Adjuster* pixelShiftSigma;
+#ifdef PIXELSHIFTDEV
+ Adjuster* pixelShiftSum;
+ Adjuster* pixelShiftMotion;
+ MyComboBoxText* pixelShiftMotionCorrection;
+ MyCheckButton* pixelShiftAutomatic;
+ MyCheckButton* pixelShiftNonGreenHorizontal;
+ MyCheckButton* pixelShiftNonGreenVertical;
+ MyCheckButton* pixelShiftNonGreenCross2;
+ MyCheckButton* pixelShiftNonGreenAmaze;
+ MyCheckButton* pixelShiftExp0;
+ MyCheckButton* pixelShiftMedian3;
+ Adjuster* pixelShiftStddevFactorGreen;
+ Adjuster* pixelShiftStddevFactorRed;
+ Adjuster* pixelShiftStddevFactorBlue;
+ Adjuster* pixelShiftNreadIso;
+ Adjuster* pixelShiftPrnu;
+ Adjuster* pixelShiftRedBlueWeight;
+#endif
+ int oldMethod;
public:
BayerProcess ();
@@ -54,9 +83,29 @@ public:
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr);
void methodChanged ();
+ void imageNumberChanged ();
void adjusterChanged (Adjuster* a, double newval);
void dcbEnhanceChanged();
- //void allEnhanceChanged();
+ void pixelShiftShowMotionChanged();
+ void pixelShiftShowMotionMaskOnlyChanged();
+ void pixelShiftHoleFillChanged();
+ void pixelShiftMedianChanged();
+ void pixelShiftMedian3Changed();
+ void pixelShiftGreenChanged();
+ void pixelShiftBlurChanged();
+ void pixelShiftLmmseChanged();
+ void pixelShiftEqualBrightChanged();
+ void pixelShiftNonGreenCrossChanged();
+ void pixelShiftMotionMethodChanged();
+#ifdef PIXELSHIFTDEV
+ void psMotionCorrectionChanged ();
+ void pixelShiftAutomaticChanged();
+ void pixelShiftNonGreenHorizontalChanged();
+ void pixelShiftNonGreenVerticalChanged();
+ void pixelShiftExp0Changed();
+ void pixelShiftNonGreenCross2Changed();
+ void pixelShiftNonGreenAmazeChanged();
+#endif
};
#endif
diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc
index 46c956436..d261da64c 100644
--- a/rtgui/cropwindow.cc
+++ b/rtgui/cropwindow.cc
@@ -61,9 +61,10 @@ ZoomStep zoomSteps[] = {
{"500%", 5.0, 5000},
{"600%", 6.0, 6000},
{"700%", 7.0, 7000},
- {"800%", 8.0, 8000}
+ {"800%", 8.0, 8000},
+ {"1600%", 16.0, 16000}
};
-#define MAXZOOMSTEPS 20
+#define MAXZOOMSTEPS 21
#define ZOOM11INDEX 13
CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow)
@@ -1034,9 +1035,21 @@ void CropWindow::pointerMoved (int bstate, int x, int y)
int imheight = cropHandler.cropPixbuf->get_height();
guint8* pix = cropHandler.cropPixbuftrue->get_pixels() + vy * cropHandler.cropPixbuf->get_rowstride() + vx * 3;
+ int rval = pix[0];
+ int gval = pix[1];
+ int bval = pix[2];
if (vx < imwidth && vy < imheight) {
+ rtengine::StagedImageProcessor* ipc = iarea->getImProcCoordinator();
+ if(ipc) {
+ procparams::ProcParams params;
+ ipc->getParams(¶ms);
+ if(params.raw.bayersensor.method == RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::none] || params.raw.xtranssensor.method == RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::none]) {
+ ImageSource *isrc = static_cast(ipc->getInitialImage());
+ isrc->getRawValues(mx, my, params.coarse.rotate, rval, gval, bval);
+ }
+ }
// pmlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]);
- pmlistener->pointerMoved (true, cropHandler.colorParams.output, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]);
+ pmlistener->pointerMoved (true, cropHandler.colorParams.output, cropHandler.colorParams.working, mx, my, rval, gval, bval);
if (pmhlistener)
// pmhlistener->pointerMoved (true, cropHandler.colorParams.working, mx, my, pix[0], pix[1], pix[2]);
diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h
index 12370a571..5601d28f3 100644
--- a/rtgui/guiutils.h
+++ b/rtgui/guiutils.h
@@ -290,6 +290,24 @@ public:
MyScrolledWindow();
};
+/**
+ * @brief subclass of Gtk::CheckButton in order to handle the last active state
+ */
+class MyCheckButton : public Gtk::CheckButton
+{
+
+ bool lastActive = false;
+ sigc::connection myConnection;
+public:
+ using CheckButton::CheckButton;
+ void setLastActive() {lastActive = get_active();};
+ void setLastActive(bool active) {lastActive = active;};
+ bool getLastActive() {return lastActive;};
+ void connect(const sigc::connection &connection) {myConnection = connection;};
+ void block(bool blocked) {myConnection.block(blocked);};
+};
+
+
/**
* @brief subclass of Gtk::ComboBox in order to handle the scrollwheel
*/
@@ -313,6 +331,7 @@ public:
class MyComboBoxText : public Gtk::ComboBoxText
{
int naturalWidth, minimumWidth;
+ sigc::connection myConnection;
bool on_scroll_event (GdkEventScroll* event);
void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const;
@@ -322,6 +341,8 @@ public:
MyComboBoxText (bool has_entry = false);
void setPreferredWidth (int minimum_width, int natural_width);
+ void connect(const sigc::connection &connection) {myConnection = connection;};
+ void block(bool blocked) {myConnection.block(blocked);};
};
/**
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 7704327bb..4d05158c0 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -360,6 +360,7 @@ void ParamsEdited::set (bool v)
icm.gampos = v;
icm.slpos = v;
raw.bayersensor.method = v;
+ raw.bayersensor.imageNum = v;
raw.bayersensor.ccSteps = v;
raw.bayersensor.exBlack0 = v;
raw.bayersensor.exBlack1 = v;
@@ -370,6 +371,35 @@ void ParamsEdited::set (bool v)
raw.bayersensor.dcbEnhance = v;
//raw.bayersensor.allEnhance = v;
raw.bayersensor.lmmseIterations = v;
+ raw.bayersensor.pixelShiftMotion = v;
+ raw.bayersensor.pixelShiftMotionCorrection = v;
+ raw.bayersensor.pixelShiftMotionCorrectionMethod = v;
+ raw.bayersensor.pixelShiftStddevFactorGreen = v;
+ raw.bayersensor.pixelShiftStddevFactorRed = v;
+ raw.bayersensor.pixelShiftStddevFactorBlue = v;
+ raw.bayersensor.pixelShiftEperIso = v;
+ raw.bayersensor.pixelShiftNreadIso = v;
+ raw.bayersensor.pixelShiftPrnu = v;
+ raw.bayersensor.pixelShiftSigma = v;
+ raw.bayersensor.pixelShiftSum = v;
+ raw.bayersensor.pixelShiftRedBlueWeight = v;
+ raw.bayersensor.pixelshiftShowMotion = v;
+ raw.bayersensor.pixelshiftShowMotionMaskOnly = v;
+ raw.bayersensor.pixelShiftAutomatic = v;
+ raw.bayersensor.pixelShiftNonGreenHorizontal = v;
+ raw.bayersensor.pixelShiftNonGreenVertical = v;
+ raw.bayersensor.pixelShiftHoleFill = v;
+ raw.bayersensor.pixelShiftMedian = v;
+ raw.bayersensor.pixelShiftMedian3 = v;
+ raw.bayersensor.pixelShiftGreen = v;
+ raw.bayersensor.pixelShiftBlur = v;
+ raw.bayersensor.pixelShiftSmooth = v;
+ raw.bayersensor.pixelShiftExp0 = v;
+ raw.bayersensor.pixelShiftLmmse = v;
+ raw.bayersensor.pixelShiftEqualBright = v;
+ raw.bayersensor.pixelShiftNonGreenCross = v;
+ raw.bayersensor.pixelShiftNonGreenCross2 = v;
+ raw.bayersensor.pixelShiftNonGreenAmaze = v;
raw.bayersensor.greenEq = v;
raw.bayersensor.linenoise = v;
raw.xtranssensor.method = v;
@@ -856,6 +886,7 @@ void ParamsEdited::initFrom (const std::vector
icm.gampos = icm.gampos && p.icm.gampos == other.icm.gampos;
icm.slpos = icm.slpos && p.icm.slpos == other.icm.slpos;
raw.bayersensor.method = raw.bayersensor.method && p.raw.bayersensor.method == other.raw.bayersensor.method;
+ raw.bayersensor.imageNum = raw.bayersensor.imageNum && p.raw.bayersensor.imageNum == other.raw.bayersensor.imageNum;
raw.bayersensor.ccSteps = raw.bayersensor.ccSteps && p.raw.bayersensor.ccSteps == other.raw.bayersensor.ccSteps;
raw.bayersensor.exBlack0 = raw.bayersensor.exBlack0 && p.raw.bayersensor.black0 == other.raw.bayersensor.black0;
raw.bayersensor.exBlack1 = raw.bayersensor.exBlack1 && p.raw.bayersensor.black1 == other.raw.bayersensor.black1;
@@ -866,6 +897,35 @@ void ParamsEdited::initFrom (const std::vector
raw.bayersensor.dcbEnhance = raw.bayersensor.dcbEnhance && p.raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance;
//raw.bayersensor.allEnhance = raw.bayersensor.allEnhance && p.raw.bayersensor.all_enhance == other.raw.bayersensor.all_enhance;
raw.bayersensor.lmmseIterations = raw.bayersensor.lmmseIterations && p.raw.bayersensor.lmmse_iterations == other.raw.bayersensor.lmmse_iterations;
+ raw.bayersensor.pixelShiftMotion = raw.bayersensor.pixelShiftMotion && p.raw.bayersensor.pixelShiftMotion == other.raw.bayersensor.pixelShiftMotion;
+ raw.bayersensor.pixelShiftMotionCorrection = raw.bayersensor.pixelShiftMotionCorrection && p.raw.bayersensor.pixelShiftMotionCorrection == other.raw.bayersensor.pixelShiftMotionCorrection;
+ raw.bayersensor.pixelShiftMotionCorrectionMethod = raw.bayersensor.pixelShiftMotionCorrectionMethod && p.raw.bayersensor.pixelShiftMotionCorrectionMethod == other.raw.bayersensor.pixelShiftMotionCorrectionMethod;
+ raw.bayersensor.pixelShiftStddevFactorGreen = raw.bayersensor.pixelShiftStddevFactorGreen && p.raw.bayersensor.pixelShiftStddevFactorGreen == other.raw.bayersensor.pixelShiftStddevFactorGreen;
+ raw.bayersensor.pixelShiftStddevFactorRed = raw.bayersensor.pixelShiftStddevFactorRed && p.raw.bayersensor.pixelShiftStddevFactorRed == other.raw.bayersensor.pixelShiftStddevFactorRed;
+ raw.bayersensor.pixelShiftStddevFactorBlue = raw.bayersensor.pixelShiftStddevFactorBlue && p.raw.bayersensor.pixelShiftStddevFactorBlue == other.raw.bayersensor.pixelShiftStddevFactorBlue;
+ raw.bayersensor.pixelShiftEperIso = raw.bayersensor.pixelShiftEperIso && p.raw.bayersensor.pixelShiftEperIso == other.raw.bayersensor.pixelShiftEperIso;
+ raw.bayersensor.pixelShiftNreadIso = raw.bayersensor.pixelShiftNreadIso && p.raw.bayersensor.pixelShiftNreadIso == other.raw.bayersensor.pixelShiftNreadIso;
+ raw.bayersensor.pixelShiftPrnu = raw.bayersensor.pixelShiftPrnu && p.raw.bayersensor.pixelShiftPrnu == other.raw.bayersensor.pixelShiftPrnu;
+ raw.bayersensor.pixelShiftSigma = raw.bayersensor.pixelShiftSigma && p.raw.bayersensor.pixelShiftSigma == other.raw.bayersensor.pixelShiftSigma;
+ raw.bayersensor.pixelShiftSum = raw.bayersensor.pixelShiftSum && p.raw.bayersensor.pixelShiftSum == other.raw.bayersensor.pixelShiftSum;
+ raw.bayersensor.pixelShiftRedBlueWeight = raw.bayersensor.pixelShiftRedBlueWeight && p.raw.bayersensor.pixelShiftRedBlueWeight == other.raw.bayersensor.pixelShiftRedBlueWeight;
+ raw.bayersensor.pixelshiftShowMotion = raw.bayersensor.pixelshiftShowMotion && p.raw.bayersensor.pixelshiftShowMotion == other.raw.bayersensor.pixelshiftShowMotion;
+ raw.bayersensor.pixelshiftShowMotionMaskOnly = raw.bayersensor.pixelshiftShowMotionMaskOnly && p.raw.bayersensor.pixelshiftShowMotionMaskOnly == other.raw.bayersensor.pixelshiftShowMotionMaskOnly;
+ raw.bayersensor.pixelShiftAutomatic = raw.bayersensor.pixelShiftAutomatic && p.raw.bayersensor.pixelShiftAutomatic == other.raw.bayersensor.pixelShiftAutomatic;
+ raw.bayersensor.pixelShiftNonGreenHorizontal = raw.bayersensor.pixelShiftNonGreenHorizontal && p.raw.bayersensor.pixelShiftNonGreenHorizontal == other.raw.bayersensor.pixelShiftNonGreenHorizontal;
+ raw.bayersensor.pixelShiftNonGreenVertical = raw.bayersensor.pixelShiftNonGreenVertical && p.raw.bayersensor.pixelShiftNonGreenVertical == other.raw.bayersensor.pixelShiftNonGreenVertical;
+ raw.bayersensor.pixelShiftHoleFill = raw.bayersensor.pixelShiftHoleFill && p.raw.bayersensor.pixelShiftHoleFill == other.raw.bayersensor.pixelShiftHoleFill;
+ raw.bayersensor.pixelShiftMedian = raw.bayersensor.pixelShiftMedian && p.raw.bayersensor.pixelShiftMedian == other.raw.bayersensor.pixelShiftMedian;
+ 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.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor;
+ raw.bayersensor.pixelShiftExp0 = raw.bayersensor.pixelShiftExp0 && p.raw.bayersensor.pixelShiftExp0 == other.raw.bayersensor.pixelShiftExp0;
+ raw.bayersensor.pixelShiftLmmse = raw.bayersensor.pixelShiftLmmse && p.raw.bayersensor.pixelShiftLmmse == other.raw.bayersensor.pixelShiftLmmse;
+ raw.bayersensor.pixelShiftEqualBright = raw.bayersensor.pixelShiftEqualBright && p.raw.bayersensor.pixelShiftEqualBright == other.raw.bayersensor.pixelShiftEqualBright;
+ 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;
+ 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.xtranssensor.method = raw.xtranssensor.method && p.raw.xtranssensor.method == other.raw.xtranssensor.method;
@@ -2242,6 +2302,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
toEdit.raw.bayersensor.method = mods.raw.bayersensor.method;
}
+ if (raw.bayersensor.imageNum) {
+ toEdit.raw.bayersensor.imageNum = mods.raw.bayersensor.imageNum;
+ }
+
if (raw.bayersensor.ccSteps) {
toEdit.raw.bayersensor.ccSteps = mods.raw.bayersensor.ccSteps;
}
@@ -2278,7 +2342,122 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
toEdit.raw.bayersensor.lmmse_iterations = mods.raw.bayersensor.lmmse_iterations;
}
- //if (raw.bayersensor.allEnhance) toEdit.raw.bayersensor.all_enhance = mods.raw.bayersensor.all_enhance;
+ if (raw.bayersensor.pixelShiftMotion) {
+ toEdit.raw.bayersensor.pixelShiftMotion = mods.raw.bayersensor.pixelShiftMotion;
+ }
+
+ if (raw.bayersensor.pixelShiftMotionCorrection) {
+ toEdit.raw.bayersensor.pixelShiftMotionCorrection = mods.raw.bayersensor.pixelShiftMotionCorrection;
+ }
+
+ if (raw.bayersensor.pixelShiftMotionCorrectionMethod) {
+ toEdit.raw.bayersensor.pixelShiftMotionCorrectionMethod = mods.raw.bayersensor.pixelShiftMotionCorrectionMethod;
+ }
+
+ if (raw.bayersensor.pixelShiftStddevFactorGreen) {
+ toEdit.raw.bayersensor.pixelShiftStddevFactorGreen = mods.raw.bayersensor.pixelShiftStddevFactorGreen;
+ }
+
+ if (raw.bayersensor.pixelShiftStddevFactorRed) {
+ toEdit.raw.bayersensor.pixelShiftStddevFactorRed = mods.raw.bayersensor.pixelShiftStddevFactorRed;
+ }
+
+ if (raw.bayersensor.pixelShiftStddevFactorBlue) {
+ toEdit.raw.bayersensor.pixelShiftStddevFactorBlue = mods.raw.bayersensor.pixelShiftStddevFactorBlue;
+ }
+
+ if (raw.bayersensor.pixelShiftEperIso) {
+ toEdit.raw.bayersensor.pixelShiftEperIso = mods.raw.bayersensor.pixelShiftEperIso;
+ }
+
+ if (raw.bayersensor.pixelShiftNreadIso) {
+ toEdit.raw.bayersensor.pixelShiftNreadIso = mods.raw.bayersensor.pixelShiftNreadIso;
+ }
+
+ if (raw.bayersensor.pixelShiftPrnu) {
+ toEdit.raw.bayersensor.pixelShiftPrnu = mods.raw.bayersensor.pixelShiftPrnu;
+ }
+
+ if (raw.bayersensor.pixelShiftSigma) {
+ toEdit.raw.bayersensor.pixelShiftSigma = mods.raw.bayersensor.pixelShiftSigma;
+ }
+
+ if (raw.bayersensor.pixelShiftSum) {
+ toEdit.raw.bayersensor.pixelShiftSum = mods.raw.bayersensor.pixelShiftSum;
+ }
+
+ if (raw.bayersensor.pixelShiftRedBlueWeight) {
+ toEdit.raw.bayersensor.pixelShiftRedBlueWeight = mods.raw.bayersensor.pixelShiftRedBlueWeight;
+ }
+
+ if (raw.bayersensor.pixelshiftShowMotion) {
+ toEdit.raw.bayersensor.pixelshiftShowMotion = mods.raw.bayersensor.pixelshiftShowMotion;
+ }
+
+ if (raw.bayersensor.pixelshiftShowMotionMaskOnly) {
+ toEdit.raw.bayersensor.pixelshiftShowMotionMaskOnly = mods.raw.bayersensor.pixelshiftShowMotionMaskOnly;
+ }
+
+ if (raw.bayersensor.pixelShiftAutomatic) {
+ toEdit.raw.bayersensor.pixelShiftAutomatic = mods.raw.bayersensor.pixelShiftAutomatic;
+ }
+
+ if (raw.bayersensor.pixelShiftNonGreenHorizontal) {
+ toEdit.raw.bayersensor.pixelShiftNonGreenHorizontal = mods.raw.bayersensor.pixelShiftNonGreenHorizontal;
+ }
+
+ if (raw.bayersensor.pixelShiftNonGreenVertical) {
+ toEdit.raw.bayersensor.pixelShiftNonGreenVertical = mods.raw.bayersensor.pixelShiftNonGreenVertical;
+ }
+
+ if (raw.bayersensor.pixelShiftHoleFill) {
+ toEdit.raw.bayersensor.pixelShiftHoleFill = mods.raw.bayersensor.pixelShiftHoleFill;
+ }
+
+ if (raw.bayersensor.pixelShiftMedian) {
+ toEdit.raw.bayersensor.pixelShiftMedian = mods.raw.bayersensor.pixelShiftMedian;
+ }
+
+ if (raw.bayersensor.pixelShiftMedian3) {
+ toEdit.raw.bayersensor.pixelShiftMedian3 = mods.raw.bayersensor.pixelShiftMedian3;
+ }
+
+ if (raw.bayersensor.pixelShiftGreen) {
+ toEdit.raw.bayersensor.pixelShiftGreen = mods.raw.bayersensor.pixelShiftGreen;
+ }
+
+ if (raw.bayersensor.pixelShiftBlur) {
+ toEdit.raw.bayersensor.pixelShiftBlur = mods.raw.bayersensor.pixelShiftBlur;
+ }
+
+ if (raw.bayersensor.pixelShiftSmooth) {
+ toEdit.raw.bayersensor.pixelShiftSmoothFactor = mods.raw.bayersensor.pixelShiftSmoothFactor;
+ }
+
+ if (raw.bayersensor.pixelShiftExp0) {
+ toEdit.raw.bayersensor.pixelShiftExp0 = mods.raw.bayersensor.pixelShiftExp0;
+ }
+
+ if (raw.bayersensor.pixelShiftLmmse) {
+ toEdit.raw.bayersensor.pixelShiftLmmse = mods.raw.bayersensor.pixelShiftLmmse;
+ }
+
+ if (raw.bayersensor.pixelShiftEqualBright) {
+ toEdit.raw.bayersensor.pixelShiftEqualBright = mods.raw.bayersensor.pixelShiftEqualBright;
+ }
+
+ if (raw.bayersensor.pixelShiftNonGreenCross) {
+ toEdit.raw.bayersensor.pixelShiftNonGreenCross = mods.raw.bayersensor.pixelShiftNonGreenCross;
+ }
+
+ if (raw.bayersensor.pixelShiftNonGreenCross2) {
+ toEdit.raw.bayersensor.pixelShiftNonGreenCross2 = mods.raw.bayersensor.pixelShiftNonGreenCross2;
+ }
+
+ if (raw.bayersensor.pixelShiftNonGreenAmaze) {
+ toEdit.raw.bayersensor.pixelShiftNonGreenAmaze = mods.raw.bayersensor.pixelShiftNonGreenAmaze;
+ }
+
if (raw.bayersensor.greenEq) {
toEdit.raw.bayersensor.greenthresh = dontforceSet && options.baBehav[ADDSET_PREPROCESS_GREENEQUIL] ? toEdit.raw.bayersensor.greenthresh + mods.raw.bayersensor.greenthresh : mods.raw.bayersensor.greenthresh;
}
@@ -2788,7 +2967,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
bool RAWParamsEdited::BayerSensor::isUnchanged() const
{
- return method && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq
+ return method && imageNum && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && greenEq
+ && 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 && pixelShiftEqualBright
&& linenoise && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen;
}
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index fc549d91a..fc69a1e48 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -682,6 +682,7 @@ public:
public:
bool method;
+ bool imageNum;
bool ccSteps;
bool exBlack0;
bool exBlack1;
@@ -691,6 +692,36 @@ public:
bool dcbIterations;
bool dcbEnhance;
bool lmmseIterations;
+ bool pixelShiftMotion;
+ bool pixelShiftMotionCorrection;
+ bool pixelShiftMotionCorrectionMethod;
+ bool pixelShiftStddevFactorGreen;
+ bool pixelShiftStddevFactorRed;
+ bool pixelShiftStddevFactorBlue;
+ bool pixelShiftEperIso;
+ bool pixelShiftNreadIso;
+ bool pixelShiftPrnu;
+ bool pixelShiftSigma;
+ bool pixelShiftSum;
+ bool pixelShiftRedBlueWeight;
+ bool pixelshiftShowMotion;
+ bool pixelshiftShowMotionMaskOnly;
+ bool pixelShiftAutomatic;
+ bool pixelShiftNonGreenHorizontal;
+ bool pixelShiftNonGreenVertical;
+ bool pixelShiftHoleFill;
+ bool pixelShiftMedian;
+ bool pixelShiftMedian3;
+ bool pixelShiftGreen;
+ bool pixelShiftBlur;
+ bool pixelShiftSmooth;
+ bool pixelShiftExp0;
+ bool pixelShiftLmmse;
+ bool pixelShiftEqualBright;
+ bool pixelShiftNonGreenCross;
+ bool pixelShiftNonGreenCross2;
+ bool pixelShiftNonGreenAmaze;
+
//bool allEnhance;
bool greenEq;
bool linenoise;
diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc
index c0cc2c87c..7cf7de15e 100644
--- a/rtgui/partialpastedlg.cc
+++ b/rtgui/partialpastedlg.cc
@@ -111,6 +111,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
raw_linenoise = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_LINEDENOISE")));
raw_greenthresh = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_GREENEQUIL")));
raw_method = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DMETHOD")));
+ raw_imagenum = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_IMAGENUM")));
raw_ccSteps = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_FALSECOLOR")));
raw_dcb_iterations = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DCBITERATIONS")));
raw_dcb_enhance = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DCBENHANCE")));
@@ -200,6 +201,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
vboxes[6]->pack_start (*raw, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*hseps[6], Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_method, Gtk::PACK_SHRINK, 2);
+ vboxes[6]->pack_start (*raw_imagenum, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_ccSteps, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_dcb_iterations, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_dcb_enhance, Gtk::PACK_SHRINK, 2);
@@ -338,7 +340,8 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
exifchConn = exifch->signal_toggled().connect (sigc::bind (sigc::mem_fun(*meta, &Gtk::CheckButton::set_inconsistent), true));
iptcConn = iptc->signal_toggled().connect (sigc::bind (sigc::mem_fun(*meta, &Gtk::CheckButton::set_inconsistent), true));
- raw_methodConn = raw_method->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
+ raw_methodConn = raw_method->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
+ raw_imagenumConn = raw_imagenum->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_ccStepsConn = raw_ccSteps->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_dcb_iterationsConn = raw_dcb_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_dcb_enhanceConn = raw_dcb_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
@@ -418,6 +421,7 @@ void PartialPasteDlg::rawToggled ()
{
raw_methodConn.block (true);
+ raw_imagenumConn.block (true);
raw_ccStepsConn.block (true);
raw_dcb_iterationsConn.block (true);
raw_dcb_enhanceConn.block (true);
@@ -444,6 +448,7 @@ void PartialPasteDlg::rawToggled ()
raw->set_inconsistent (false);
raw_method->set_active (raw->get_active ());
+ raw_imagenum->set_active (raw->get_active ());
raw_ccSteps->set_active (raw->get_active ());
raw_dcb_iterations->set_active (raw->get_active ());
raw_dcb_enhance->set_active (raw->get_active ());
@@ -468,6 +473,7 @@ void PartialPasteDlg::rawToggled ()
ff_ClipControl->set_active (raw->get_active ());
raw_methodConn.block (false);
+ raw_imagenumConn.block (false);
raw_ccStepsConn.block (false);
raw_dcb_iterationsConn.block (false);
raw_dcb_enhanceConn.block (false);
@@ -847,6 +853,10 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
filterPE.raw.xtranssensor.method = falsePE.raw.xtranssensor.method;
}
+ if (!raw_imagenum->get_active ()) {
+ filterPE.raw.bayersensor.imageNum = falsePE.raw.bayersensor.imageNum;
+ }
+
if (!raw_ccSteps->get_active ()) {
filterPE.raw.bayersensor.ccSteps = falsePE.raw.bayersensor.ccSteps;
filterPE.raw.xtranssensor.ccSteps = falsePE.raw.xtranssensor.ccSteps;
diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h
index 99249eefd..177b0b720 100644
--- a/rtgui/partialpastedlg.h
+++ b/rtgui/partialpastedlg.h
@@ -107,6 +107,7 @@ public:
Gtk::CheckButton* raw_linenoise;
Gtk::CheckButton* raw_greenthresh;
Gtk::CheckButton* raw_method;
+ Gtk::CheckButton* raw_imagenum;
Gtk::CheckButton* raw_ccSteps;
Gtk::CheckButton* raw_dcb_iterations;
Gtk::CheckButton* raw_dcb_enhance;
@@ -129,7 +130,7 @@ public:
sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, prsharpeningConn, perspectiveConn, commonTransConn;
sigc::connection exifchConn, iptcConn, icmConn;
sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn, ff_ClipControlConn;
- sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn;
+ sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_imagenumConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn;
public:
PartialPasteDlg (const Glib::ustring &title, Gtk::Window* parent);
diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc
index 62f543d4a..1be475d59 100644
--- a/rtgui/thumbnail.cc
+++ b/rtgui/thumbnail.cc
@@ -138,7 +138,7 @@ void Thumbnail::_generateThumbnailImage ()
if ( tpp == nullptr ) {
quick = false;
- tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, tw, th, 1, pparams.wb.equal, TRUE);
+ tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, tw, th, 1, pparams.wb.equal, TRUE, pparams.raw.bayersensor.imageNum);
}
if (tpp) {