diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index ad7bb5b5d..d1eaf800c 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -753,7 +753,7 @@ void Crop::update(int todo) } if (need_fattal) { - parent->ipf.dehaze(f); + parent->ipf.dehaze(f, params.dehaze); parent->ipf.ToneMapFattal02(f); } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 08e7a862f..21d2f7681 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -553,7 +553,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) fattal_11_dcrop_cache = nullptr; } - ipf.dehaze(orig_prev); + ipf.dehaze(orig_prev, params->dehaze); ipf.ToneMapFattal02(orig_prev); if (oprevi != orig_prev) { diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index cb63a5e3d..6e522a5b1 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -44,12 +44,13 @@ namespace procparams class ProcParams; +struct DehazeParams; struct DirPyrDenoiseParams; +struct LocallabParams; struct SharpeningParams; struct VibranceParams; struct VignettingParams; struct WaveletParams; -struct LocallabParams; } @@ -400,8 +401,7 @@ public: void Badpixelscam(CieImage * ncie, double radius, int thresh, int mode, float chrom, bool hotbad); void BadpixelsLab(LabImage * lab, double radius, int thresh, float chrom); - void dehaze(Imagefloat *rgb); - void dehazeloc(Imagefloat *rgb, float deha, float depth); + void dehaze(Imagefloat *rgb, const DehazeParams &dehazeParams); void ToneMapFattal02(Imagefloat *rgb); void localContrast(LabImage *lab); void localContrastloc(LabImage *lab, int scale, int rad, float amo, float darkn, float lightn, float **loctemp); diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 5f1e6ab88..7feaf3321 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -209,9 +209,9 @@ void extract_channels(Imagefloat *img, array2D &r, array2D &g, arr } // namespace -void ImProcFunctions::dehaze(Imagefloat *img) +void ImProcFunctions::dehaze(Imagefloat *img, const DehazeParams &dehazeParams) { - if (!params->dehaze.enabled) { + if (!dehazeParams.enabled) { return; } @@ -219,7 +219,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) const int W = img->getWidth(); const int H = img->getHeight(); - const float strength = LIM01(float(params->dehaze.strength) / 100.f * 0.9f); + const float strength = LIM01(float(dehazeParams.strength) / 100.f * 0.9f); if (options.rtSettings.verbose) { std::cout << "dehaze: strength = " << strength << std::endl; @@ -288,7 +288,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) std::cout << "dehaze: max distance is " << max_t << std::endl; } - float depth = -float(params->dehaze.depth) / 100.f; + float depth = -float(dehazeParams.depth) / 100.f; const float t0 = max(1e-3f, std::exp(depth * max_t)); const float teps = 1e-3f; #ifdef _OPENMP @@ -308,7 +308,7 @@ void ImProcFunctions::dehaze(Imagefloat *img) } } float mt = max(t[y][x], t0, tl + teps, tu + teps); - if (params->dehaze.showDepthMap) { + if (dehazeParams.showDepthMap) { img->r(y, x) = img->g(y, x) = img->b(y, x) = LIM01(1.f - mt); } else { float r = (rgb[0] - ambient[0]) / mt + ambient[0]; @@ -325,123 +325,4 @@ void ImProcFunctions::dehaze(Imagefloat *img) img->normalizeFloatTo65535(); } - -void ImProcFunctions::dehazeloc(Imagefloat *img, float deha, float depth) -{ - - img->normalizeFloatTo1(); - - const int W = img->getWidth(); - const int H = img->getHeight(); - float strength = deha;//LIM01(float(params->locallab.dehaze) / 100.f * 0.9f); - - if (options.rtSettings.verbose) { - std::cout << "dehaze: strength = " << strength << std::endl; - } - - array2D dark(W, H); - - int patchsize = max(int(5 / scale), 2); - int npatches = 0; - float ambient[3]; - array2D &t_tilde = dark; - float max_t = 0.f; - - { - array2D R(W, H); - array2D G(W, H); - array2D B(W, H); - extract_channels(img, R, G, B, patchsize, 1e-1, multiThread); - - patchsize = max(max(W, H) / 600, 2); - npatches = get_dark_channel(R, G, B, dark, patchsize, nullptr, false, multiThread); - DEBUG_DUMP(dark); - - max_t = estimate_ambient_light(R, G, B, dark, patchsize, npatches, ambient); - - if (options.rtSettings.verbose) { - std::cout << "dehaze: ambient light is " - << ambient[0] << ", " << ambient[1] << ", " << ambient[2] - << std::endl; - } - - get_dark_channel(R, G, B, dark, patchsize, ambient, true, multiThread); - } - - if (min(ambient[0], ambient[1], ambient[2]) < 0.01f) { - if (options.rtSettings.verbose) { - std::cout << "dehaze: no haze detected" << std::endl; - } - img->normalizeFloatTo65535(); - return; // probably no haze at all - } - - DEBUG_DUMP(t_tilde); - -#ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - dark[y][x] = 1.f - strength * dark[y][x]; - } - } - - const int radius = patchsize * 4; - const float epsilon = 1e-5; - array2D &t = t_tilde; - - { - array2D guideB(W, H, img->b.ptrs, ARRAY2D_BYREFERENCE); - guidedFilter(guideB, t_tilde, t, radius, epsilon, multiThread); - } - - DEBUG_DUMP(t); - - if (options.rtSettings.verbose) { - std::cout << "dehaze: max distance is " << max_t << std::endl; - } - - float dept = depth; - if (options.rtSettings.verbose) { - std::cout << "dehaze: depth = " << dept << std::endl; - } - - const float t0 = max(1e-3f, std::exp(dept * max_t)); - const float teps = 1e-3f; -#ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - for (int y = 0; y < H; ++y) { - for (int x = 0; x < W; ++x) { - // ensure that the transmission is such that to avoid clipping... - float rgb[3] = { img->r(y, x), img->g(y, x), img->b(y, x) }; - // ... t >= tl to avoid negative values - float tl = 1.f - min(rgb[0]/ambient[0], rgb[1]/ambient[1], rgb[2]/ambient[2]); - // ... t >= tu to avoid values > 1 - float tu = t0 - teps; - for (int c = 0; c < 3; ++c) { - if (ambient[c] < 1) { - tu = max(tu, (rgb[c] - ambient[c])/(1.f - ambient[c])); - } - } - float mt = max(t[y][x], t0, tl + teps, tu + teps); - if (params->dehaze.showDepthMap) { - img->r(y, x) = img->g(y, x) = img->b(y, x) = 1.f - mt; - } else { - float r = (rgb[0] - ambient[0]) / mt + ambient[0]; - float g = (rgb[1] - ambient[1]) / mt + ambient[1]; - float b = (rgb[2] - ambient[2]) / mt + ambient[2]; - - img->r(y, x) = r; - img->g(y, x) = g; - img->b(y, x) = b; - } - } - } - - img->normalizeFloatTo65535(); -} - - } // namespace rtengine diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 1a5952712..2c74652a1 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -6044,14 +6044,16 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o Imagefloat *tmpImage = nullptr; if (lp.dehaze > 0) { + const float depthcombi = 0.3f * params->locallab.spots.at(sp).neigh + 0.15f * (500.f - params->locallab.spots.at(sp).vart); + DehazeParams dehazeParams; + dehazeParams.enabled = true; + dehazeParams.strength = 0.9f * lp.dehaze + 0.3f * lp.str; + dehazeParams.showDepthMap = false; + dehazeParams.depth = LIM(depthcombi, 0.f, 100.f); + tmpImage = new Imagefloat(bfw, bfh); lab2rgb(*bufreti, *tmpImage, params->icm.workingProfile); - float deha = LIM01(float(0.9f * lp.dehaze + 0.3f * lp.str) / 100.f * 0.9f); - float depthcombi = 0.3f * params->locallab.spots.at(sp).neigh + 0.15f * (500.f - params->locallab.spots.at(sp).vart); - float depth = -LIM01(depthcombi / 100.f); - - dehazeloc(tmpImage, deha, depth); - + dehaze(tmpImage, dehazeParams); rgb2lab(*tmpImage, *bufreti, params->icm.workingProfile); delete tmpImage; @@ -6096,14 +6098,16 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o bufreti = new LabImage(Wd, Hd); if (lp.dehaze > 0) { + const float depthcombi = 0.3f * params->locallab.spots.at(sp).neigh + 0.15f * (500.f - params->locallab.spots.at(sp).vart); + DehazeParams dehazeParams; + dehazeParams.enabled = true; + dehazeParams.strength = 0.9f * lp.dehaze + 0.3f * lp.str; + dehazeParams.showDepthMap = false; + dehazeParams.depth = LIM(depthcombi, 0.f, 100.f); + tmpImage = new Imagefloat(Wd, Hd); lab2rgb(*original, *tmpImage, params->icm.workingProfile); - float deha = LIM01(float(0.9f * lp.dehaze + 0.3f * lp.str) / 100.f * 0.9f); - float depthcombi = 0.3f * params->locallab.spots.at(sp).neigh + 0.15f * (500.f - params->locallab.spots.at(sp).vart); - float depth = -LIM01(depthcombi / 100.f); - - dehazeloc(tmpImage, deha, depth); - + dehaze(tmpImage, dehazeParams); rgb2lab(*tmpImage, *bufreti, params->icm.workingProfile); delete tmpImage; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index c41393b3f..ee0930618 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1227,7 +1227,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ipf.firstAnalysis (baseImg, params, hist16); - ipf.dehaze(baseImg); + ipf.dehaze(baseImg, params.dehaze); ipf.ToneMapFattal02(baseImg); // perform transform diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 6c4247a70..f551d7ca6 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -872,7 +872,7 @@ private: ipf.firstAnalysis(baseImg, params, hist16); - ipf.dehaze(baseImg); + ipf.dehaze(baseImg, params.dehaze); ipf.ToneMapFattal02(baseImg); // perform transform (excepted resizing)