diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index 7f0147b4c..839b90a47 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -74,8 +74,13 @@ extern const Settings* settings; extern MyMutex *fftwMutex; -void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, const int height, const Median medianType, const int iterations, const int numThreads, float **buffer) +namespace { + +template +void do_median_denoise(float **src, float **dst, float upperBound, const int width, const int height, const ImProcFunctions::Median medianType, const int iterations, const int numThreads, float **buffer) { + typedef ImProcFunctions::Median Median; + int border = 1; switch (medianType) { @@ -156,13 +161,17 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, switch (medianType) { case Median::TYPE_3X3_SOFT: { for (; j < width - border; ++j) { - medianOut[i][j] = median( - medianIn[i - 1][j], - medianIn[i][j - 1], - medianIn[i][j], - medianIn[i][j + 1], - medianIn[i + 1][j] - ); + if (!useUpperBound || medianIn[i][j] <= upperBound) { + medianOut[i][j] = median( + medianIn[i - 1][j], + medianIn[i][j - 1], + medianIn[i][j], + medianIn[i][j + 1], + medianIn[i + 1][j] + ); + } else { + medianOut[i][j] = medianIn[i][j]; + } } break; @@ -170,17 +179,21 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, case Median::TYPE_3X3_STRONG: { for (; j < width - border; ++j) { - medianOut[i][j] = median( - medianIn[i - 1][j - 1], - medianIn[i - 1][j], - medianIn[i - 1][j + 1], - medianIn[i][j - 1], - medianIn[i][j], - medianIn[i][j + 1], - medianIn[i + 1][j - 1], - medianIn[i + 1][j], - medianIn[i + 1][j + 1] - ); + if (!useUpperBound || medianIn[i][j] <= upperBound) { + medianOut[i][j] = median( + medianIn[i - 1][j - 1], + medianIn[i - 1][j], + medianIn[i - 1][j + 1], + medianIn[i][j - 1], + medianIn[i][j], + medianIn[i][j + 1], + medianIn[i + 1][j - 1], + medianIn[i + 1][j], + medianIn[i + 1][j + 1] + ); + } else { + medianOut[i][j] = medianIn[i][j]; + } } break; @@ -188,21 +201,25 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, case Median::TYPE_5X5_SOFT: { for (; j < width - border; ++j) { - medianOut[i][j] = median( - medianIn[i - 2][j], - medianIn[i - 1][j - 1], - medianIn[i - 1][j], - medianIn[i - 1][j + 1], - medianIn[i][j - 2], - medianIn[i][j - 1], - medianIn[i][j], - medianIn[i][j + 1], - medianIn[i][j + 2], - medianIn[i + 1][j - 1], - medianIn[i + 1][j], - medianIn[i + 1][j + 1], - medianIn[i + 2][j] - ); + if (!useUpperBound || medianIn[i][j] <= upperBound) { + medianOut[i][j] = median( + medianIn[i - 2][j], + medianIn[i - 1][j - 1], + medianIn[i - 1][j], + medianIn[i - 1][j + 1], + medianIn[i][j - 2], + medianIn[i][j - 1], + medianIn[i][j], + medianIn[i][j + 1], + medianIn[i][j + 2], + medianIn[i + 1][j - 1], + medianIn[i + 1][j], + medianIn[i + 1][j + 1], + medianIn[i + 2][j] + ); + } else { + medianOut[i][j] = medianIn[i][j]; + } } break; @@ -210,8 +227,7 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, case Median::TYPE_5X5_STRONG: { #ifdef __SSE2__ - - for (; j < width - border - 3; j += 4) { + for (; !useUpperBound && j < width - border - 3; j += 4) { STVFU( medianOut[i][j], median( @@ -245,35 +261,38 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, } #endif - for (; j < width - border; ++j) { - medianOut[i][j] = median( - medianIn[i - 2][j - 2], - medianIn[i - 2][j - 1], - medianIn[i - 2][j], - medianIn[i - 2][j + 1], - medianIn[i - 2][j + 2], - medianIn[i - 1][j - 2], - medianIn[i - 1][j - 1], - medianIn[i - 1][j], - medianIn[i - 1][j + 1], - medianIn[i - 1][j + 2], - medianIn[i][j - 2], - medianIn[i][j - 1], - medianIn[i][j], - medianIn[i][j + 1], - medianIn[i][j + 2], - medianIn[i + 1][j - 2], - medianIn[i + 1][j - 1], - medianIn[i + 1][j], - medianIn[i + 1][j + 1], - medianIn[i + 1][j + 2], - medianIn[i + 2][j - 2], - medianIn[i + 2][j - 1], - medianIn[i + 2][j], - medianIn[i + 2][j + 1], - medianIn[i + 2][j + 2] - ); + if (!useUpperBound || medianIn[i][j] <= upperBound) { + medianOut[i][j] = median( + medianIn[i - 2][j - 2], + medianIn[i - 2][j - 1], + medianIn[i - 2][j], + medianIn[i - 2][j + 1], + medianIn[i - 2][j + 2], + medianIn[i - 1][j - 2], + medianIn[i - 1][j - 1], + medianIn[i - 1][j], + medianIn[i - 1][j + 1], + medianIn[i - 1][j + 2], + medianIn[i][j - 2], + medianIn[i][j - 1], + medianIn[i][j], + medianIn[i][j + 1], + medianIn[i][j + 2], + medianIn[i + 1][j - 2], + medianIn[i + 1][j - 1], + medianIn[i + 1][j], + medianIn[i + 1][j + 1], + medianIn[i + 1][j + 2], + medianIn[i + 2][j - 2], + medianIn[i + 2][j - 1], + medianIn[i + 2][j], + medianIn[i + 2][j + 1], + medianIn[i + 2][j + 2] + ); + } else { + medianOut[i][j] = medianIn[i][j]; + } } break; @@ -283,7 +302,7 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, #ifdef __SSE2__ std::array vpp ALIGNED16; - for (; j < width - border - 3; j += 4) { + for (; !useUpperBound && j < width - border - 3; j += 4) { for (int kk = 0, ii = -border; ii <= border; ++ii) { for (int jj = -border; jj <= border; ++jj, ++kk) { vpp[kk] = LVFU(medianIn[i + ii][j + jj]); @@ -296,15 +315,19 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, #endif std::array pp; - + for (; j < width - border; ++j) { - for (int kk = 0, ii = -border; ii <= border; ++ii) { - for (int jj = -border; jj <= border; ++jj, ++kk) { - pp[kk] = medianIn[i + ii][j + jj]; + if (!useUpperBound || medianIn[i][j] <= upperBound) { + for (int kk = 0, ii = -border; ii <= border; ++ii) { + for (int jj = -border; jj <= border; ++jj, ++kk) { + pp[kk] = medianIn[i + ii][j + jj]; + } } + + medianOut[i][j] = median(pp); + } else { + medianOut[i][j] = medianIn[i][j]; } - - medianOut[i][j] = median(pp); } break; @@ -314,7 +337,7 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, #ifdef __SSE2__ std::array vpp ALIGNED16; - for (; j < width - border - 3; j += 4) { + for (; !useUpperBound && j < width - border - 3; j += 4) { for (int kk = 0, ii = -border; ii <= border; ++ii) { for (int jj = -border; jj <= border; ++jj, ++kk) { vpp[kk] = LVFU(medianIn[i + ii][j + jj]); @@ -327,15 +350,19 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, #endif std::array pp; - + for (; j < width - border; ++j) { - for (int kk = 0, ii = -border; ii <= border; ++ii) { - for (int jj = -border; jj <= border; ++jj, ++kk) { - pp[kk] = medianIn[i + ii][j + jj]; + if (!useUpperBound || medianIn[i][j] <= upperBound) { + for (int kk = 0, ii = -border; ii <= border; ++ii) { + for (int jj = -border; jj <= border; ++jj, ++kk) { + pp[kk] = medianIn[i + ii][j + jj]; + } } + + medianOut[i][j] = median(pp); + } else { + medianOut[i][j] = medianIn[i][j]; } - - medianOut[i][j] = median(pp); } for (; j < width; ++j) { @@ -382,6 +409,21 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, } } +} // namespace + + +void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, const int height, const Median medianType, const int iterations, const int numThreads, float **buffer) +{ + do_median_denoise(src, dst, width, height, 0.f, medianType, iterations, numThreads, buffer); +} + + +void ImProcFunctions::Median_Denoise(float **src, float **dst, float upperBound, const int width, const int height, const Median medianType, const int iterations, const int numThreads, float **buffer) +{ + do_median_denoise(src, dst, upperBound, width, height, medianType, iterations, numThreads, buffer); +} + + void ImProcFunctions::Tile_calc(int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip) { diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 46ad670fa..364713fc1 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -305,6 +305,7 @@ public: void Median_Denoise ( float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr); + void Median_Denoise ( float **src, float **dst, float upperBound, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr); void RGB_denoise (int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve, const NoiseCurve & noiseCCurve, float &chaut, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &nresi, float &highresi); void RGB_denoise_infoGamCurve (const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope); void RGB_denoise_info (Imagefloat * src, Imagefloat * provicalc, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false); diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index 5b2f88107..1f415737a 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -1196,7 +1196,6 @@ void ImProcFunctions::ToneMapFattal02(Imagefloat *rgb) #else int num_threads = 1; #endif - Array2Df Yr_med(w, h); float r = float(std::max(w, h)) / float(RT_dimension_cap); Median med; if (r >= 3) { @@ -1208,18 +1207,7 @@ void ImProcFunctions::ToneMapFattal02(Imagefloat *rgb) } else { med = Median::TYPE_3X3_STRONG; } - Median_Denoise(Yr, Yr_med, w, h, med, 1, num_threads); - -#ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - for (int y = 0; y < h; y++) { - for (int x = 0; x < w; x++) { - if (Yr(x, y) <= luminance_noise_floor) { - Yr(x, y) = Yr_med(x, y); - } - } - } + Median_Denoise(Yr, Yr, luminance_noise_floor, w, h, med, 1, num_threads); }