diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index c08afc154..3ae8f1d65 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -1165,8 +1165,6 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte orw = bw; orh = bh; - ProcParams& params = parent->params; - parent->ipf.transCoord (parent->fw, parent->fh, bx1, by1, bw, bh, orx, ory, orw, orh); if (check_need_larger_crop_for_lcp_distortion (parent->fw, parent->fh, orx, ory, orw, orh, parent->params)) { diff --git a/rtengine/ipshadowshighlights.cc b/rtengine/ipshadowshighlights.cc index c9eb9d058..4d5cc465a 100644 --- a/rtengine/ipshadowshighlights.cc +++ b/rtengine/ipshadowshighlights.cc @@ -18,12 +18,10 @@ * along with RawTherapee. If not, see . */ -#ifdef _OPENMP -#include -#endif - #include "improcfun.h" #include "gauss.h" +#include "sleef.c" +#include "opthelper.h" namespace rtengine { @@ -38,36 +36,39 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab) array2D mask(width, height); const float sigma = params->sh.radius * 5.f / scale; + LUTf f(32768); const auto apply = [&](int amount, int tonalwidth, bool hl) -> void { const float thresh = tonalwidth * 327.68f; const float scale = hl ? (thresh > 0.f ? 0.9f / thresh : 1.f) : thresh * 0.9f; + #ifdef _OPENMP - #pragma omp parallel for if (multiThread) -#endif - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - float l = lab->L[y][x]; - if (hl) { - mask[y][x] = (l > thresh) ? 1.f : std::pow(l * scale, 4); - } else { - mask[y][x] = l <= thresh ? 1.f : std::pow(scale / l, 4); - } - } - } -#ifdef _OPENMP - #pragma omp parallel + #pragma omp parallel if (multiThread) #endif { + +#ifdef _OPENMP + #pragma omp for +#endif + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + float l = lab->L[y][x]; + if (hl) { + mask[y][x] = (l > thresh) ? 1.f : pow4(l * scale); + } else { + mask[y][x] = l <= thresh ? 1.f : pow4(scale / l); + } + } + } + gaussianBlur(mask, mask, width, height, sigma); } const float base = std::pow(4.f, float(amount)/100.f); const float gamma = hl ? base : 1.f / base; - LUTf f(32768); const float contrast = std::pow(2.f, float(amount)/100.f); DiagonalCurve sh_contrast({ DCT_NURBS, @@ -77,20 +78,41 @@ void ImProcFunctions::shadowsHighlights(LabImage *lab) 0.375, std::pow(0.375 / 0.25, contrast) * 0.25, 1, 1 }); + + if(!hl) { #ifdef _OPENMP - #pragma omp parallel for if (multiThread) + #pragma omp parallel for if (multiThread) #endif - for (int l = 0; l < 32768; ++l) { - auto base = std::pow(l / 32768.f, gamma); - if (!hl) { + for (int l = 0; l < 32768; ++l) { + auto base = pow_F(l / 32768.f, gamma); // get a bit more contrast in the shadows base = sh_contrast.getVal(base); + f[l] = base * 32768.f; } - f[l] = base * 32768.f; - } - + } else { +#ifdef __SSE2__ + vfloat c32768v = F2V(32768.f); + vfloat lv = _mm_setr_ps(0,1,2,3); + vfloat fourv = F2V(4.f); + vfloat gammav = F2V(gamma); + for (int l = 0; l < 32768; l += 4) { + vfloat basev = pow_F(lv / c32768v, gammav); + STVFU(f[l], basev * c32768v); + lv += fourv; + } +#else #ifdef _OPENMP - #pragma omp parallel for if (multiThread) + #pragma omp parallel for if (multiThread) +#endif + for (int l = 0; l < 32768; ++l) { + auto base = pow_F(l / 32768.f, gamma); + f[l] = base * 32768.f; + } +#endif + } + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) if (multiThread) #endif for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { diff --git a/rtengine/rt_math.h b/rtengine/rt_math.h index 8a32f52b9..8d55b492e 100644 --- a/rtengine/rt_math.h +++ b/rtengine/rt_math.h @@ -38,6 +38,12 @@ constexpr T SQR(T x) return x * x; } +template +constexpr T pow4(T x) +{ + return SQR(SQR(x)); +} + template constexpr const T& min(const T& a) { diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h index e2838c2c0..4ea8120db 100644 --- a/rtgui/ppversion.h +++ b/rtgui/ppversion.h @@ -1,16 +1,18 @@ #pragma once // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes -#define PPVERSION 331 +#define PPVERSION 332 #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified /* Log of version changes - 331 2018-14-02 + 332 2018-04-26 + new Shadows/Highlights tool + 331 2018-02-14 changed wavelet.Lmethod to int - 330 2018-20-01 + 330 2018-01-20 Added 'Auto-matched Tone Curve' button, performing histogram matching - 329 2017-12-09 + 329 2017-09-12 Added 'Enabled' flag for Channel Mixer, RGB Curves, HSV Equalizer and L*a*b* Adjustments 328 2017-11-22 Fix wrong type of ff_clipControl diff --git a/rtgui/shadowshighlights.cc b/rtgui/shadowshighlights.cc index f450205bb..60cd7a209 100644 --- a/rtgui/shadowshighlights.cc +++ b/rtgui/shadowshighlights.cc @@ -37,7 +37,7 @@ ShadowsHighlights::ShadowsHighlights () : FoldableToolPanel(this, "shadowshighli pack_start (*Gtk::manage (new Gtk::HSeparator())); - radius = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_RADIUS"), 5, 100, 1, 30)); + radius = Gtk::manage (new Adjuster (M("TP_SHADOWSHLIGHTS_RADIUS"), 5, 100, 1, 40)); pack_start (*radius); radius->setAdjusterListener (this);