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);