diff --git a/rtdata/languages/default b/rtdata/languages/default index a9f19778f..3911dc12a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2180,7 +2180,8 @@ TP_RAW_HD_TOOLTIP;Lower values make hot/dead pixel detection more aggressive, bu TP_RAW_HPHD;HPHD TP_RAW_IGV;IGV TP_RAW_IMAGENUM;Sub-image -TP_RAW_IMAGENUM_TOOLTIP;Some raw files consist of several sub-images (Pentax/Sony Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel).\n\nWhen using any demosaicing method other than Pixel Shift, this selects which sub-image is used.\n\nWhen using the Pixel Shift demosaicing method on a Pixel Shift raw, all sub-images are used, and this selects which sub-image should be used for moving parts. +TP_RAW_IMAGENUM_SN;SN mode +TP_RAW_IMAGENUM_TOOLTIP;Some raw files consist of several sub-images (Pentax/Sony Pixel Shift, Pentax 3-in-1 HDR, Canon Dual Pixel, Fuji EXR).\n\nWhen using any demosaicing method other than Pixel Shift, this selects which sub-image is used.\n\nWhen using the Pixel Shift demosaicing method on a Pixel Shift raw, all sub-images are used, and this selects which sub-image should be used for moving parts. TP_RAW_LABEL;Demosaicing TP_RAW_LMMSE;LMMSE TP_RAW_LMMSEITERATIONS;LMMSE enhancement steps diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 8596ac4a7..20d21a7ec 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -58,23 +58,20 @@ namespace { #endif -int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, float *ambient, bool clip, bool multithread) +int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, const float ambient[3], bool clip, bool multithread) { const int W = R.width(); const int H = R.height(); - int npatches = 0; - #ifdef _OPENMP - #pragma omp parallel for reduction(+:npatches) if (multithread) + #pragma omp parallel for if (multithread) #endif for (int y = 0; y < H; y += patchsize) { - int pH = min(y+patchsize, H); - for (int x = 0; x < W; x += patchsize, ++npatches) { + const int pH = min(y + patchsize, H); + for (int x = 0; x < W; x += patchsize) { float val = RT_INFINITY_F; - int pW = min(x+patchsize, W); + const int pW = min(x + patchsize, W); for (int yy = y; yy < pH; ++yy) { - float yval = RT_INFINITY_F; for (int xx = x; xx < pW; ++xx) { float r = R[yy][xx]; float g = G[yy][xx]; @@ -84,20 +81,19 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr g /= ambient[1]; b /= ambient[2]; } - yval = min(yval, r, g, b); + val = min(val, r, g, b); } - val = min(val, yval); } if (clip) { val = LIM01(val); } for (int yy = y; yy < pH; ++yy) { - std::fill(dst[yy]+x, dst[yy]+pW, val); + std::fill(dst[yy] + x, dst[yy] + pW, val); } } } - return npatches; + return (W / patchsize + ((W % patchsize) > 0)) * (H / patchsize + ((H % patchsize) > 0)); } @@ -121,7 +117,7 @@ float estimate_ambient_light(const array2D &R, const array2D &G, c std::priority_queue p; for (int y = 0; y < H; y += patchsize) { for (int x = 0; x < W; x += patchsize) { - if (!OOG(dark[y][x], 1.f)) { + if (!OOG(dark[y][x], 1.f - 1e-5f)) { p.push(dark[y][x]); } } @@ -221,7 +217,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) const int W = img->getWidth(); const int H = img->getHeight(); - float strength = LIM01(float(params->dehaze.strength) / 100.f * 0.9f); + const float strength = LIM01(float(params->dehaze.strength) / 100.f * 0.9f); if (options.rtSettings.verbose) { std::cout << "dehaze: strength = " << strength << std::endl; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 2cac1fed3..81e97d3ee 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1801,6 +1801,19 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens copyOriginalPixels(raw, riFrames[i], rid, rif, *rawDataFrames[i]); } } + } else if (numFrames == 2 && currFrame == 2) { // average the frames + if(!rawDataBuffer[0]) { + rawDataBuffer[0] = new array2D; + } + rawDataFrames[1] = rawDataBuffer[0]; + copyOriginalPixels(raw, riFrames[1], rid, rif, *rawDataFrames[1]); + copyOriginalPixels(raw, ri, rid, rif, rawData); + + for (int i = 0; i < H; ++i) { + for (int j = 0; j < W; ++j) { + rawData[i][j] = (rawData[i][j] + (*rawDataFrames[1])[i][j]) * 0.5f; + } + } } else { copyOriginalPixels(raw, ri, rid, rif, rawData); } diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 208867e5f..53adaafc0 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -201,8 +201,13 @@ public: static void init (); static void cleanup (); void setCurrentFrame(unsigned int frameNum) override { - currFrame = std::min(numFrames - 1, frameNum); - ri = riFrames[currFrame]; + if (numFrames == 2 && frameNum == 2) { // special case for averaging of two frames + currFrame = frameNum; + ri = riFrames[0]; + } else { + currFrame = std::min(numFrames - 1, frameNum); + ri = riFrames[currFrame]; + } } int getFrameCount() override {return numFrames;} int getFlatFieldAutoClipValue() override {return flatFieldAutoClipValue;} diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 74cf27dde..279e68bd6 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -730,7 +730,10 @@ void BayerProcess::FrameCountChanged(int n, int frameNum) entry << i; imageNumber->append(entry.str()); } - imageNumber->set_active(std::min(frameNum, n - 1)); + if (n == 2) { + imageNumber->append(M("TP_RAW_IMAGENUM_SN")); + } + imageNumber->set_active(std::min(frameNum, n == 2 ? n : n - 1)); if (n == 1) { imageNumberBox->hide(); } else {