From d17f71eb72216ab0e7c196408064006ad45bf519 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Mon, 30 Dec 2019 15:27:17 +0100 Subject: [PATCH 01/11] Applying geometric transformations leads to dark artifacts in combination with capture sharpening, fixes #5588 --- rtengine/iptransform.cc | 140 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 132 insertions(+), 8 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index af513536e..736fa0620 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -111,6 +111,31 @@ inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, g = vhadd(weight * gv); b = vhadd(weight * bv); } + +inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul) +{ + constexpr float A = -0.85f; + + // Vertical + const float t1Vert = A * (Dy - Dy * Dy); + const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy; + const vfloat w3Vert = F2V(t1Vert * Dy); + const vfloat w2Vert = F2V(t1Vert * Dy - t1Vert + t2Vert); + const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert); + const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy)); + + const vfloat rv = (w0Vert * xlogf(LVFU(src->r(ys, xs))) + w1Vert * xlogf(LVFU(src->r(ys + 1, xs)))) + (w2Vert * xlogf(LVFU(src->r(ys + 2, xs))) + w3Vert * xlogf(LVFU(src->r(ys + 3, xs)))); + const vfloat gv = (w0Vert * xlogf(LVFU(src->g(ys, xs))) + w1Vert * xlogf(LVFU(src->g(ys + 1, xs)))) + (w2Vert * xlogf(LVFU(src->g(ys + 2, xs))) + w3Vert * xlogf(LVFU(src->g(ys + 3, xs)))); + const vfloat bv = (w0Vert * xlogf(LVFU(src->b(ys, xs))) + w1Vert * xlogf(LVFU(src->b(ys + 1, xs)))) + (w2Vert * xlogf(LVFU(src->b(ys + 2, xs))) + w3Vert * xlogf(LVFU(src->b(ys + 3, xs)))); + + // Horizontal + const float t1Hor = A * (Dx - Dx * Dx); + const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; + const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx)); + r = mul * xexpf(vhadd(weight * rv)); + g = mul * xexpf(vhadd(weight * gv)); + b = mul * xexpf(vhadd(weight * bv)); +} #else inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul) { @@ -143,6 +168,38 @@ inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, g = mul * (gv[0] * w0Hor + gv[1] * w1Hor + gv[2] * w2Hor + gv[3] * w3Hor); b = mul * (bv[0] * w0Hor + bv[1] * w1Hor + bv[2] * w2Hor + bv[3] * w3Hor); } + +inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul) +{ + constexpr float A = -0.85f; + + // Vertical + const float t1Vert = A * (Dy - Dy * Dy); + const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy; + const float w3Vert = t1Vert * Dy; + const float w2Vert = t1Vert * Dy - t1Vert + t2Vert; + const float w1Vert = 1.f - (t1Vert * Dy) - t2Vert; + const float w0Vert = t1Vert - (t1Vert * Dy); + + float rv[4], gv[4], bv[4]; + for (int i = 0; i < 4; ++i) { + rv[i] = w0Vert * xlogf(src->r(ys, xs + i)) + w1Vert * xlogf(src->r(ys + 1, xs + i)) + w2Vert * xlogf(src->r(ys + 2, xs + i)) + w3Vert * xlogf(src->r(ys + 3, xs + i)); + gv[i] = w0Vert * xlogf(src->g(ys, xs + i)) + w1Vert * xlogf(src->g(ys + 1, xs + i)) + w2Vert * xlogf(src->g(ys + 2, xs + i)) + w3Vert * xlogf(src->g(ys + 3, xs + i)); + bv[i] = w0Vert * xlogf(src->b(ys, xs + i)) + w1Vert * xlogf(src->b(ys + 1, xs + i)) + w2Vert * xlogf(src->b(ys + 2, xs + i)) + w3Vert * xlogf(src->b(ys + 3, xs + i)); + } + + // Horizontal + const float t1Hor = A * (Dx - Dx * Dx); + const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; + const float w3Hor = t1Hor * Dx; + const float w2Hor = t1Hor * Dx - t1Hor + t2Hor; + const float w1Hor = 1.f - (t1Hor * Dx) - t2Hor; + const float w0Hor = t1Hor - (t1Hor * Dx); + + r = mul * xexpf(rv[0] * w0Hor + rv[1] * w1Hor + rv[2] * w2Hor + rv[3] * w3Hor); + g = mul * xexpf(gv[0] * w0Hor + gv[1] * w1Hor + gv[2] * w2Hor + gv[3] * w3Hor); + b = mul * xexpf(bv[0] * w0Hor + bv[1] * w1Hor + bv[2] * w2Hor + bv[3] * w3Hor); +} #endif #ifdef __SSE2__ inline void interpolateTransformChannelsCubic(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul) @@ -165,6 +222,27 @@ inline void interpolateTransformChannelsCubic(const float* const* src, int xs, i const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx)); dest = mul * vhadd(weight * cv); } + +inline void interpolateTransformChannelsCubicLog(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul) +{ + constexpr float A = -0.85f; + + // Vertical + const float t1Vert = A * (Dy - Dy * Dy); + const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy; + const vfloat w3Vert = F2V(t1Vert * Dy); + const vfloat w2Vert = F2V(t1Vert * Dy - t1Vert + t2Vert); + const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert); + const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy)); + + const vfloat cv = (w0Vert * xlogf(LVFU(src[ys][xs])) + w1Vert * xlogf(LVFU(src[ys + 1][xs]))) + (w2Vert * xlogf(LVFU(src[ys + 2][xs])) + w3Vert * xlogf(LVFU(src[ys + 3][xs]))); + + // Horizontal + const float t1Hor = A * (Dx - Dx * Dx); + const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; + const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx)); + dest = mul * xexpf(vhadd(weight * cv)); +} #else inline void interpolateTransformChannelsCubic(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul) { @@ -193,6 +271,34 @@ inline void interpolateTransformChannelsCubic(const float* const* src, int xs, i dest = mul * (cv[0] * w0Hor + cv[1] * w1Hor + cv[2] * w2Hor + cv[3] * w3Hor); } + +inline void interpolateTransformChannelsCubicLog(const float* const* src, int xs, int ys, float Dx, float Dy, float& dest, float mul) +{ + constexpr float A = -0.85f; + + // Vertical + const float t1Vert = A * (Dy - Dy * Dy); + const float t2Vert = (3.f - 2.f * Dy) * Dy * Dy; + const float w3Vert = t1Vert * Dy; + const float w2Vert = t1Vert * Dy - t1Vert + t2Vert; + const float w1Vert = 1.f - (t1Vert * Dy) - t2Vert; + const float w0Vert = t1Vert - (t1Vert * Dy); + + float cv[4]; + for (int i = 0; i < 4; ++i) { + cv[i] = w0Vert * xlogf(src[ys][xs + i]) + w1Vert * xlogf(src[ys + 1][xs + i]) + w2Vert * xlogf(src[ys + 2][xs + i]) + w3Vert * xlogf(src[ys + 3][xs + i]); + } + + // Horizontal + const float t1Hor = A * (Dx - Dx * Dx); + const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; + const float w3Hor = t1Hor * Dx; + const float w2Hor = t1Hor * Dx - t1Hor + t2Hor; + const float w1Hor = 1.f - (t1Hor * Dx) - t2Hor; + const float w0Hor = t1Hor - (t1Hor * Dx); + + dest = mul * xexpf(cv[0] * w0Hor + cv[1] * w1Hor + cv[2] * w2Hor + cv[3] * w3Hor); +} #endif } @@ -922,6 +1028,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I const double ascale = params->commonTrans.autofill ? getTransformAutoFill(oW, oH, pLCPMap) : 1.0; const bool darkening = (params->vignetting.amount <= 0.0); + const bool useLog = params->pdsharpening.enabled; const double centerFactorx = cx - w2; const double centerFactory = cy - h2; @@ -1011,14 +1118,26 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) { // all interpolation pixels inside image - if (enableCA) { - interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); - } else if (!highQuality) { - transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); - transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); - transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); + if (!useLog) { + if (enableCA) { + interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); + } else if (!highQuality) { + transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); + } else { + interpolateTransformCubic(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); + } } else { - interpolateTransformCubic(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); + if (enableCA) { + interpolateTransformChannelsCubicLog(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); + } else if (!highQuality) { + transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); + } else { + interpolateTransformCubicLog(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); + } } } else { // edge pixels @@ -1054,6 +1173,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap) { assert(pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()); + const bool useLog = params->pdsharpening.enabled; float** chOrig[3]; chOrig[0] = original->r.ptrs; @@ -1089,7 +1209,11 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans // multiplier for vignetting correction if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) { // all interpolation pixels inside image - interpolateTransformChannelsCubic (chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0); + if (!useLog) { + interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0); + } else { + interpolateTransformChannelsCubicLog(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], 1.0); + } } else { // edge pixels int y1 = LIM (yc, 0, original->getHeight() - 1); From bcb7df44dfe5c8507ea4b7ac7cde319ec51ac501 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Tue, 31 Dec 2019 15:23:24 +0100 Subject: [PATCH 02/11] Log transform: fix segfault --- rtengine/iptransform.cc | 30 +++++++++++++----------------- rtengine/sleef.h | 24 ++++++++++++++++++++++++ rtengine/sleefsseavx.c | 24 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 736fa0620..77fa57985 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -124,9 +124,9 @@ inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert); const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy)); - const vfloat rv = (w0Vert * xlogf(LVFU(src->r(ys, xs))) + w1Vert * xlogf(LVFU(src->r(ys + 1, xs)))) + (w2Vert * xlogf(LVFU(src->r(ys + 2, xs))) + w3Vert * xlogf(LVFU(src->r(ys + 3, xs)))); - const vfloat gv = (w0Vert * xlogf(LVFU(src->g(ys, xs))) + w1Vert * xlogf(LVFU(src->g(ys + 1, xs)))) + (w2Vert * xlogf(LVFU(src->g(ys + 2, xs))) + w3Vert * xlogf(LVFU(src->g(ys + 3, xs)))); - const vfloat bv = (w0Vert * xlogf(LVFU(src->b(ys, xs))) + w1Vert * xlogf(LVFU(src->b(ys + 1, xs)))) + (w2Vert * xlogf(LVFU(src->b(ys + 2, xs))) + w3Vert * xlogf(LVFU(src->b(ys + 3, xs)))); + const vfloat rv = (w0Vert * xlogf1(LVFU(src->r(ys, xs))) + w1Vert * xlogf1(LVFU(src->r(ys + 1, xs)))) + (w2Vert * xlogf1(LVFU(src->r(ys + 2, xs))) + w3Vert * xlogf1(LVFU(src->r(ys + 3, xs)))); + const vfloat gv = (w0Vert * xlogf1(LVFU(src->g(ys, xs))) + w1Vert * xlogf1(LVFU(src->g(ys + 1, xs)))) + (w2Vert * xlogf1(LVFU(src->g(ys + 2, xs))) + w3Vert * xlogf1(LVFU(src->g(ys + 3, xs)))); + const vfloat bv = (w0Vert * xlogf1(LVFU(src->b(ys, xs))) + w1Vert * xlogf1(LVFU(src->b(ys + 1, xs)))) + (w2Vert * xlogf1(LVFU(src->b(ys + 2, xs))) + w3Vert * xlogf1(LVFU(src->b(ys + 3, xs)))); // Horizontal const float t1Hor = A * (Dx - Dx * Dx); @@ -183,9 +183,9 @@ inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int float rv[4], gv[4], bv[4]; for (int i = 0; i < 4; ++i) { - rv[i] = w0Vert * xlogf(src->r(ys, xs + i)) + w1Vert * xlogf(src->r(ys + 1, xs + i)) + w2Vert * xlogf(src->r(ys + 2, xs + i)) + w3Vert * xlogf(src->r(ys + 3, xs + i)); - gv[i] = w0Vert * xlogf(src->g(ys, xs + i)) + w1Vert * xlogf(src->g(ys + 1, xs + i)) + w2Vert * xlogf(src->g(ys + 2, xs + i)) + w3Vert * xlogf(src->g(ys + 3, xs + i)); - bv[i] = w0Vert * xlogf(src->b(ys, xs + i)) + w1Vert * xlogf(src->b(ys + 1, xs + i)) + w2Vert * xlogf(src->b(ys + 2, xs + i)) + w3Vert * xlogf(src->b(ys + 3, xs + i)); + rv[i] = w0Vert * xlogf1(src->r(ys, xs + i)) + w1Vert * xlogf1(src->r(ys + 1, xs + i)) + w2Vert * xlogf1(src->r(ys + 2, xs + i)) + w3Vert * xlogf1(src->r(ys + 3, xs + i)); + gv[i] = w0Vert * xlogf1(src->g(ys, xs + i)) + w1Vert * xlogf1(src->g(ys + 1, xs + i)) + w2Vert * xlogf1(src->g(ys + 2, xs + i)) + w3Vert * xlogf1(src->g(ys + 3, xs + i)); + bv[i] = w0Vert * xlogf1(src->b(ys, xs + i)) + w1Vert * xlogf1(src->b(ys + 1, xs + i)) + w2Vert * xlogf1(src->b(ys + 2, xs + i)) + w3Vert * xlogf1(src->b(ys + 3, xs + i)); } // Horizontal @@ -235,7 +235,7 @@ inline void interpolateTransformChannelsCubicLog(const float* const* src, int xs const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert); const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy)); - const vfloat cv = (w0Vert * xlogf(LVFU(src[ys][xs])) + w1Vert * xlogf(LVFU(src[ys + 1][xs]))) + (w2Vert * xlogf(LVFU(src[ys + 2][xs])) + w3Vert * xlogf(LVFU(src[ys + 3][xs]))); + const vfloat cv = (w0Vert * xlogf1(LVFU(src[ys][xs])) + w1Vert * xlogf1(LVFU(src[ys + 1][xs]))) + (w2Vert * xlogf1(LVFU(src[ys + 2][xs])) + w3Vert * xlogf1(LVFU(src[ys + 3][xs]))); // Horizontal const float t1Hor = A * (Dx - Dx * Dx); @@ -286,7 +286,7 @@ inline void interpolateTransformChannelsCubicLog(const float* const* src, int xs float cv[4]; for (int i = 0; i < 4; ++i) { - cv[i] = w0Vert * xlogf(src[ys][xs + i]) + w1Vert * xlogf(src[ys + 1][xs + i]) + w2Vert * xlogf(src[ys + 2][xs + i]) + w3Vert * xlogf(src[ys + 3][xs + i]); + cv[i] = w0Vert * xlogf1(src[ys][xs + i]) + w1Vert * xlogf1(src[ys + 1][xs + i]) + w2Vert * xlogf1(src[ys + 2][xs + i]) + w3Vert * xlogf1(src[ys + 3][xs + i]); } // Horizontal @@ -1118,23 +1118,19 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I if (yc > 0 && yc < original->getHeight() - 2 && xc > 0 && xc < original->getWidth() - 2) { // all interpolation pixels inside image - if (!useLog) { + if (!highQuality) { + transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); + } else if (!useLog) { if (enableCA) { interpolateTransformChannelsCubic(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); - } else if (!highQuality) { - transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); - transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); - transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); } else { interpolateTransformCubic(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); } } else { if (enableCA) { interpolateTransformChannelsCubicLog(chOrig[c], xc - 1, yc - 1, Dx, Dy, chTrans[c][y][x], vignmul); - } else if (!highQuality) { - transformed->r(y, x) = vignmul * (original->r(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r(yc, xc + 1) * Dx * (1.0 - Dy) + original->r(yc + 1, xc) * (1.0 - Dx) * Dy + original->r(yc + 1, xc + 1) * Dx * Dy); - transformed->g(y, x) = vignmul * (original->g(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g(yc, xc + 1) * Dx * (1.0 - Dy) + original->g(yc + 1, xc) * (1.0 - Dx) * Dy + original->g(yc + 1, xc + 1) * Dx * Dy); - transformed->b(y, x) = vignmul * (original->b(yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b(yc, xc + 1) * Dx * (1.0 - Dy) + original->b(yc + 1, xc) * (1.0 - Dx) * Dy + original->b(yc + 1, xc + 1) * Dx * Dy); } else { interpolateTransformCubicLog(original, xc - 1, yc - 1, Dx, Dy, transformed->r(y, x), transformed->g(y, x), transformed->b(y, x), vignmul); } diff --git a/rtengine/sleef.h b/rtengine/sleef.h index 30c059010..7b7d5995f 100644 --- a/rtengine/sleef.h +++ b/rtengine/sleef.h @@ -1206,6 +1206,30 @@ __inline float xlogf(float d) { return x; } +__inline float xlogf1(float d) { // does xlogf(vmaxf(d, 1.f)) but faster + float x, x2, t, m; + int e; + + e = ilogbp1f(d * 0.7071f); + m = ldexpkf(d, -e); + + x = (m-1.0f) / (m+1.0f); + x2 = x * x; + + t = 0.2371599674224853515625f; + t = mlaf(t, x2, 0.285279005765914916992188f); + t = mlaf(t, x2, 0.400005519390106201171875f); + t = mlaf(t, x2, 0.666666567325592041015625f); + t = mlaf(t, x2, 2.0f); + + x = x * t + 0.693147180559945286226764f * e; + + if (xisinff(d)) x = rtengine::RT_INFINITY_F; + if (d <= 1.f) x = 0; + + return x; +} + __inline float xexpf(float d) { if(d<=-104.0f) return 0.0f; diff --git a/rtengine/sleefsseavx.c b/rtengine/sleefsseavx.c index 1982c7c4c..0af516f9b 100644 --- a/rtengine/sleefsseavx.c +++ b/rtengine/sleefsseavx.c @@ -1253,6 +1253,30 @@ static INLINE vfloat xlogf(vfloat d) { return x; } +static INLINE vfloat xlogf1(vfloat d) { // does xlogf(vmaxf(d, 1.f)) but faster + vfloat x, x2, t, m; + vint2 e; + + e = vilogbp1f(vmulf(d, vcast_vf_f(0.7071f))); + m = vldexpf(d, vsubi2(vcast_vi2_i(0), e)); + + x = vdivf(vaddf(vcast_vf_f(-1.0f), m), vaddf(vcast_vf_f(1.0f), m)); + x2 = vmulf(x, x); + + t = vcast_vf_f(0.2371599674224853515625f); + t = vmlaf(t, x2, vcast_vf_f(0.285279005765914916992188f)); + t = vmlaf(t, x2, vcast_vf_f(0.400005519390106201171875f)); + t = vmlaf(t, x2, vcast_vf_f(0.666666567325592041015625f)); + t = vmlaf(t, x2, vcast_vf_f(2.0f)); + + x = vaddf(vmulf(x, t), vmulf(vcast_vf_f(0.693147180559945286226764f), vcast_vf_vi2(e))); + + x = vself(vmaskf_ispinf(d), vcast_vf_f(INFINITYf), x); + x = vselfnotzero(vmaskf_le(d, vcast_vf_f(1.f)), x); + + return x; +} + static INLINE vfloat xlogf0(vfloat d) { vfloat x, x2, t, m; vint2 e; From 58d8e66b7245e63b39c0d92db7775d0ede14cc04 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Tue, 31 Dec 2019 19:09:06 +0100 Subject: [PATCH 03/11] Log transform: speedup, #5588 --- rtengine/iptransform.cc | 76 ++++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 77fa57985..67647b7ef 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -86,6 +86,29 @@ float normn (float a, float b, int n) } } +void logEncode(rtengine::Imagefloat *original, bool multiThread) { + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic, 16) if(multiThread) +#endif + + for (int y = 0; y < original->getHeight(); ++y) { + int x = 0; +#ifdef __SSE2__ + for (; x < original->getWidth() - 3; x += 4) { + STVFU(original->r(y, x), xlogf1(LVFU(original->r(y, x)))); + STVFU(original->g(y, x), xlogf1(LVFU(original->g(y, x)))); + STVFU(original->b(y, x), xlogf1(LVFU(original->b(y, x)))); + } +#endif + for (; x < original->getWidth(); ++x) { + original->r(y, x) = xlogf1(original->r(y, x)); + original->g(y, x) = xlogf1(original->g(y, x)); + original->b(y, x) = xlogf1(original->b(y, x)); + } + } +} + #ifdef __SSE2__ inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul) { @@ -124,9 +147,9 @@ inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert); const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy)); - const vfloat rv = (w0Vert * xlogf1(LVFU(src->r(ys, xs))) + w1Vert * xlogf1(LVFU(src->r(ys + 1, xs)))) + (w2Vert * xlogf1(LVFU(src->r(ys + 2, xs))) + w3Vert * xlogf1(LVFU(src->r(ys + 3, xs)))); - const vfloat gv = (w0Vert * xlogf1(LVFU(src->g(ys, xs))) + w1Vert * xlogf1(LVFU(src->g(ys + 1, xs)))) + (w2Vert * xlogf1(LVFU(src->g(ys + 2, xs))) + w3Vert * xlogf1(LVFU(src->g(ys + 3, xs)))); - const vfloat bv = (w0Vert * xlogf1(LVFU(src->b(ys, xs))) + w1Vert * xlogf1(LVFU(src->b(ys + 1, xs)))) + (w2Vert * xlogf1(LVFU(src->b(ys + 2, xs))) + w3Vert * xlogf1(LVFU(src->b(ys + 3, xs)))); + const vfloat rv = (w0Vert * LVFU(src->r(ys, xs)) + w1Vert * LVFU(src->r(ys + 1, xs))) + (w2Vert * LVFU(src->r(ys + 2, xs)) + w3Vert * LVFU(src->r(ys + 3, xs))); + const vfloat gv = (w0Vert * LVFU(src->g(ys, xs)) + w1Vert * LVFU(src->g(ys + 1, xs))) + (w2Vert * LVFU(src->g(ys + 2, xs)) + w3Vert * LVFU(src->g(ys + 3, xs))); + const vfloat bv = (w0Vert * LVFU(src->b(ys, xs)) + w1Vert * LVFU(src->b(ys + 1, xs))) + (w2Vert * LVFU(src->b(ys + 2, xs)) + w3Vert * LVFU(src->b(ys + 3, xs))); // Horizontal const float t1Hor = A * (Dx - Dx * Dx); @@ -183,9 +206,9 @@ inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int float rv[4], gv[4], bv[4]; for (int i = 0; i < 4; ++i) { - rv[i] = w0Vert * xlogf1(src->r(ys, xs + i)) + w1Vert * xlogf1(src->r(ys + 1, xs + i)) + w2Vert * xlogf1(src->r(ys + 2, xs + i)) + w3Vert * xlogf1(src->r(ys + 3, xs + i)); - gv[i] = w0Vert * xlogf1(src->g(ys, xs + i)) + w1Vert * xlogf1(src->g(ys + 1, xs + i)) + w2Vert * xlogf1(src->g(ys + 2, xs + i)) + w3Vert * xlogf1(src->g(ys + 3, xs + i)); - bv[i] = w0Vert * xlogf1(src->b(ys, xs + i)) + w1Vert * xlogf1(src->b(ys + 1, xs + i)) + w2Vert * xlogf1(src->b(ys + 2, xs + i)) + w3Vert * xlogf1(src->b(ys + 3, xs + i)); + rv[i] = w0Vert * src->r(ys, xs + i) + w1Vert * src->r(ys + 1, xs + i) + w2Vert * src->r(ys + 2, xs + i) + w3Vert * src->r(ys + 3, xs + i); + gv[i] = w0Vert * src->g(ys, xs + i) + w1Vert * src->g(ys + 1, xs + i) + w2Vert * src->g(ys + 2, xs + i) + w3Vert * src->g(ys + 3, xs + i); + bv[i] = w0Vert * src->b(ys, xs + i) + w1Vert * src->b(ys + 1, xs + i) + w2Vert * src->b(ys + 2, xs + i) + w3Vert * src->b(ys + 3, xs + i); } // Horizontal @@ -235,7 +258,7 @@ inline void interpolateTransformChannelsCubicLog(const float* const* src, int xs const vfloat w1Vert = F2V(1.f - (t1Vert * Dy) - t2Vert); const vfloat w0Vert = F2V(t1Vert - (t1Vert * Dy)); - const vfloat cv = (w0Vert * xlogf1(LVFU(src[ys][xs])) + w1Vert * xlogf1(LVFU(src[ys + 1][xs]))) + (w2Vert * xlogf1(LVFU(src[ys + 2][xs])) + w3Vert * xlogf1(LVFU(src[ys + 3][xs]))); + const vfloat cv = (w0Vert * LVFU(src[ys][xs]) + w1Vert * LVFU(src[ys + 1][xs])) + (w2Vert * LVFU(src[ys + 2][xs]) + w3Vert * LVFU(src[ys + 3][xs])); // Horizontal const float t1Hor = A * (Dx - Dx * Dx); @@ -286,7 +309,7 @@ inline void interpolateTransformChannelsCubicLog(const float* const* src, int xs float cv[4]; for (int i = 0; i < 4; ++i) { - cv[i] = w0Vert * xlogf1(src[ys][xs + i]) + w1Vert * xlogf1(src[ys + 1][xs + i]) + w2Vert * xlogf1(src[ys + 2][xs + i]) + w3Vert * xlogf1(src[ys + 3][xs + i]); + cv[i] = w0Vert * src[ys][xs + i] + w1Vert * src[ys + 1][xs + i] + w2Vert * src[ys + 2][xs + i] + w3Vert * src[ys + 3][xs + i]; } // Horizontal @@ -953,6 +976,7 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap) { + BENCHFUN // set up stuff, depending on the mode we are const bool enableLCPDist = pLCPMap && params->lensProf.useDist; const bool enableCA = highQuality && needsCA(); @@ -1028,10 +1052,13 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I const double ascale = params->commonTrans.autofill ? getTransformAutoFill(oW, oH, pLCPMap) : 1.0; const bool darkening = (params->vignetting.amount <= 0.0); - const bool useLog = params->pdsharpening.enabled; + const bool useLog = params->pdsharpening.enabled && highQuality; const double centerFactorx = cx - w2; const double centerFactory = cy - h2; + if (useLog) { + logEncode(original, multiThread); + } // main cycle #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 16) if(multiThread) @@ -1142,12 +1169,22 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I const int x1 = LIM(xc, 0, original->getWidth() - 1); const int x2 = LIM(xc + 1, 0, original->getWidth() - 1); - if (enableCA) { - chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); + if (useLog) { + if (enableCA) { + chTrans[c][y][x] = vignmul * xexpf(chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); + } else { + transformed->r(y, x) = vignmul * xexpf(original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); + transformed->g(y, x) = vignmul * xexpf(original->g(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g(y1, x2) * Dx * (1.0 - Dy) + original->g(y2, x1) * (1.0 - Dx) * Dy + original->g(y2, x2) * Dx * Dy); + transformed->b(y, x) = vignmul * xexpf(original->b(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b(y1, x2) * Dx * (1.0 - Dy) + original->b(y2, x1) * (1.0 - Dx) * Dy + original->b(y2, x2) * Dx * Dy); + } } else { - transformed->r(y, x) = vignmul * (original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); - transformed->g(y, x) = vignmul * (original->g(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g(y1, x2) * Dx * (1.0 - Dy) + original->g(y2, x1) * (1.0 - Dx) * Dy + original->g(y2, x2) * Dx * Dy); - transformed->b(y, x) = vignmul * (original->b(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b(y1, x2) * Dx * (1.0 - Dy) + original->b(y2, x1) * (1.0 - Dx) * Dy + original->b(y2, x2) * Dx * Dy); + if (enableCA) { + chTrans[c][y][x] = vignmul * (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); + } else { + transformed->r(y, x) = vignmul * (original->r(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r(y1, x2) * Dx * (1.0 - Dy) + original->r(y2, x1) * (1.0 - Dx) * Dy + original->r(y2, x2) * Dx * Dy); + transformed->g(y, x) = vignmul * (original->g(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g(y1, x2) * Dx * (1.0 - Dy) + original->g(y2, x1) * (1.0 - Dx) * Dy + original->g(y2, x2) * Dx * Dy); + transformed->b(y, x) = vignmul * (original->b(y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b(y1, x2) * Dx * (1.0 - Dy) + original->b(y2, x1) * (1.0 - Dx) * Dy + original->b(y2, x2) * Dx * Dy); + } } } } else { @@ -1181,6 +1218,10 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans chTrans[1] = transformed->g.ptrs; chTrans[2] = transformed->b.ptrs; + if (useLog) { + logEncode(original, multiThread); + } + #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif @@ -1216,8 +1257,11 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans int y2 = LIM (yc + 1, 0, original->getHeight() - 1); int x1 = LIM (xc, 0, original->getWidth() - 1); int x2 = LIM (xc + 1, 0, original->getWidth() - 1); - - chTrans[c][y][x] = (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); + if (!useLog) { + chTrans[c][y][x] = (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); + } else { + chTrans[c][y][x] = (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); + } } } else { // not valid (source pixel x,y not inside source image, etc.) From 399a0055c61b9c03479e36f07a08b2c1d7d70a09 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Tue, 31 Dec 2019 20:07:39 +0100 Subject: [PATCH 04/11] Log transform: Fix broken build --- rtengine/iptransform.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 67647b7ef..8d89b96cc 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -976,7 +976,7 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap) { - BENCHFUN + // set up stuff, depending on the mode we are const bool enableLCPDist = pLCPMap && params->lensProf.useDist; const bool enableCA = highQuality && needsCA(); From 6302084804b24de7b4bcb44b2e7774464282c15b Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Wed, 1 Jan 2020 14:52:15 +0100 Subject: [PATCH 05/11] sleef: use our own replacement of rint. Based on code from Alberto Griggio, but further optimized for SSE --- rtengine/sleef.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/rtengine/sleef.h b/rtengine/sleef.h index 7b7d5995f..1a953953c 100644 --- a/rtengine/sleef.h +++ b/rtengine/sleef.h @@ -894,6 +894,15 @@ __inline double xlog1p(double a) { #define R_LN2f 1.442695040888963407359924681001892137426645954152985934135449406931f +#ifdef __SSE2__ +__inline int xrintf(float x) { + return _mm_cvt_ss2si(_mm_set_ss(x)); +} +#else +__inline int xrintf(float x) { + return x + (x < 0 ? -0.5f : 0.5f); +} +#endif __inline int32_t floatToRawIntBits(float d) { union { float f; @@ -980,7 +989,7 @@ __inline float xsinf(float d) { int q; float u, s; - q = rint(d * rtengine::RT_1_PI_F); + q = xrintf(d * rtengine::RT_1_PI_F); d = mlaf(q, -PI4_Af*4, d); d = mlaf(q, -PI4_Bf*4, d); @@ -1009,7 +1018,7 @@ __inline float xcosf(float d) { int q; float u, s; - q = 1 + 2*rint(d * rtengine::RT_1_PI_F - 0.5f); + q = 1 + 2*xrintf(d * rtengine::RT_1_PI_F - 0.5f); d = mlaf(q, -PI4_Af*2, d); d = mlaf(q, -PI4_Bf*2, d); @@ -1041,7 +1050,7 @@ __inline float2 xsincosf(float d) { float u, s, t; float2 r; - q = rint(d * rtengine::RT_2_PI_F); + q = xrintf(d * rtengine::RT_2_PI_F); s = d; @@ -1083,7 +1092,7 @@ __inline float xtanf(float d) { int q; float u, s, x; - q = rint(d * (float)(2 * rtengine::RT_1_PI)); + q = xrintf(d * (float)(2 * rtengine::RT_1_PI)); x = d; @@ -1233,7 +1242,7 @@ __inline float xlogf1(float d) { // does xlogf(vmaxf(d, 1.f)) but faster __inline float xexpf(float d) { if(d<=-104.0f) return 0.0f; - int q = rint(d * R_LN2f); + int q = xrintf(d * R_LN2f); float s, u; s = mlaf(q, -L2Uf, d); From 52f7c2c5311b5a43cc6fd499f36b4c325ee59aa7 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Wed, 1 Jan 2020 15:18:47 +0100 Subject: [PATCH 06/11] Log transform: further speedup --- rtengine/iptransform.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 8d89b96cc..caa5b7e4e 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -155,9 +155,11 @@ inline void interpolateTransformCubicLog(rtengine::Imagefloat* src, int xs, int const float t1Hor = A * (Dx - Dx * Dx); const float t2Hor = (3.f - 2.f * Dx) * Dx * Dx; const vfloat weight = _mm_set_ps(t1Hor * Dx, t1Hor * Dx - t1Hor + t2Hor, 1.f - (t1Hor * Dx) - t2Hor, t1Hor - (t1Hor * Dx)); - r = mul * xexpf(vhadd(weight * rv)); - g = mul * xexpf(vhadd(weight * gv)); - b = mul * xexpf(vhadd(weight * bv)); + const vfloat tempv = _mm_setr_ps(vhadd(weight * rv), vhadd(weight * gv), vhadd(weight * bv), 0.f); + const vfloat resultv = xexpf(tempv); + r = mul * resultv[0]; + g = mul * resultv[1]; + b = mul * resultv[2]; } #else inline void interpolateTransformCubic(rtengine::Imagefloat* src, int xs, int ys, float Dx, float Dy, float &r, float &g, float &b, float mul) From 085c68fc2985b2d556398f78ed411cf985ee67d6 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Wed, 1 Jan 2020 19:06:02 +0100 Subject: [PATCH 07/11] Log tranform: fix bug in preview mode --- rtengine/improcfun.h | 6 ++--- rtengine/iptransform.cc | 48 +++++++++++++++++++++++++-------------- rtengine/simpleprocess.cc | 2 +- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 661f399ef..c1a4a5979 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -84,8 +84,8 @@ class ImProcFunctions void calcVignettingParams(int oW, int oH, const procparams::VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul); void transformLuminanceOnly(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH); - void transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap); - void transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap); + void transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap, bool useOriginalBuffer); + void transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer); bool needsCA() const; bool needsDistortion() const; @@ -156,7 +156,7 @@ public: // void colorCurve (LabImage* lold, LabImage* lnew); void sharpening(LabImage* lab, const procparams::SharpeningParams &sharpenParam, bool showMask = false); void sharpeningcam(CieImage* ncie, float** buffer, bool showMask = false); - void transform(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage); + void transform(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage, bool useOriginalBuffer = false); float resizeScale(const procparams::ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb(LabImage* lab, Image8* image); void resize(Imagefloat* src, Imagefloat* dst, float dScale); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index caa5b7e4e..fc79dcae4 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -86,25 +86,25 @@ float normn (float a, float b, int n) } } -void logEncode(rtengine::Imagefloat *original, bool multiThread) { +void logEncode(rtengine::Imagefloat *src, rtengine::Imagefloat *dest, bool multiThread) { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 16) if(multiThread) #endif - for (int y = 0; y < original->getHeight(); ++y) { + for (int y = 0; y < src->getHeight(); ++y) { int x = 0; #ifdef __SSE2__ - for (; x < original->getWidth() - 3; x += 4) { - STVFU(original->r(y, x), xlogf1(LVFU(original->r(y, x)))); - STVFU(original->g(y, x), xlogf1(LVFU(original->g(y, x)))); - STVFU(original->b(y, x), xlogf1(LVFU(original->b(y, x)))); + for (; x < src->getWidth() - 3; x += 4) { + STVFU(dest->r(y, x), xlogf1(LVFU(src->r(y, x)))); + STVFU(dest->g(y, x), xlogf1(LVFU(src->g(y, x)))); + STVFU(dest->b(y, x), xlogf1(LVFU(src->b(y, x)))); } #endif - for (; x < original->getWidth(); ++x) { - original->r(y, x) = xlogf1(original->r(y, x)); - original->g(y, x) = xlogf1(original->g(y, x)); - original->b(y, x) = xlogf1(original->b(y, x)); + for (; x < src->getWidth(); ++x) { + dest->r(y, x) = xlogf1(src->r(y, x)); + dest->g(y, x) = xlogf1(src->g(y, x)); + dest->b(y, x) = xlogf1(src->b(y, x)); } } } @@ -536,7 +536,7 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, - int rawRotationDeg, bool fullImage) + int rawRotationDeg, bool fullImage, bool useOriginalBuffer) { double focalLen = metadata->getFocalLen(); double focalLen35mm = metadata->getFocalLen35mm(); @@ -584,10 +584,10 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, dest = tmpimg.get(); } } - transformGeneral(highQuality, original, dest, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get()); + transformGeneral(highQuality, original, dest, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get(), useOriginalBuffer); if (highQuality && dest != transformed) { - transformLCPCAOnly(dest, transformed, cx, cy, pLCPMap.get()); + transformLCPCAOnly(dest, transformed, cx, cy, pLCPMap.get(), useOriginalBuffer); } } } @@ -976,7 +976,7 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat* } -void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap) +void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap, bool useOriginalBuffer) { // set up stuff, depending on the mode we are @@ -1058,8 +1058,15 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I const double centerFactorx = cx - w2; const double centerFactory = cy - h2; + std::unique_ptr tempLog; if (useLog) { - logEncode(original, multiThread); + if (!useOriginalBuffer) { + tempLog.reset(new Imagefloat(original->getWidth(), original->getHeight())); + logEncode(original, tempLog.get(), multiThread); + original = tempLog.get(); + } else { + logEncode(original, original, multiThread); + } } // main cycle #ifdef _OPENMP @@ -1205,7 +1212,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I } -void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap) +void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer) { assert(pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()); const bool useLog = params->pdsharpening.enabled; @@ -1220,8 +1227,15 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans chTrans[1] = transformed->g.ptrs; chTrans[2] = transformed->b.ptrs; + std::unique_ptr tempLog; if (useLog) { - logEncode(original, multiThread); + if (!useOriginalBuffer) { + tempLog.reset(new Imagefloat(original->getWidth(), original->getHeight())); + logEncode(original, tempLog.get(), multiThread); + original = tempLog.get(); + } else { + logEncode(original, original, multiThread); + } } #ifdef _OPENMP diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index c35fc7431..3811c0c80 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -880,7 +880,7 @@ private: trImg = new Imagefloat (fw, fh); } ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, - imgsrc->getMetaData(), imgsrc->getRotateDegree(), true); + imgsrc->getMetaData(), imgsrc->getRotateDegree(), true, true); if(trImg != baseImg) { delete baseImg; baseImg = trImg; From 2ce6e6d1d389bed4dfd82833ddf082920bc9fcd0 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Thu, 2 Jan 2020 14:35:27 +0100 Subject: [PATCH 08/11] skip unnecessary transform --- rtengine/dcrop.cc | 75 +++++++++++++++++------------------ rtengine/improccoordinator.cc | 4 +- rtengine/improcfun.h | 2 +- rtengine/iptransform.cc | 9 ++++- rtengine/rtthumbnail.cc | 10 ++--- rtengine/simpleprocess.cc | 2 +- 6 files changed, 52 insertions(+), 50 deletions(-) diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index a6889b954..890003ee0 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -173,8 +173,6 @@ void Crop::update(int todo) int widIm = parent->fw;//full image int heiIm = parent->fh; - bool needstransform = parent->ipf.needsTransform(); - if (todo & (M_INIT | M_LINDENOISE | M_HDR)) { MyMutex::MyLock lock(parent->minit); // Also used in improccoord @@ -766,8 +764,9 @@ void Crop::update(int todo) } } + const bool needstransform = parent->ipf.needsTransform(skips(parent->fw, skip), skips(parent->fh, skip), parent->imgsrc->getRotateDegree(), parent->imgsrc->getMetaData()); // transform - if (needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled)) { + if (needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled)) { if (!transCrop) { transCrop = new Imagefloat(cropw, croph); } @@ -784,10 +783,7 @@ void Crop::update(int todo) baseCrop = transCrop; } } else { - if (transCrop) { - delete transCrop; - } - + delete transCrop; transCrop = nullptr; } @@ -1167,41 +1163,42 @@ bool Crop::setCropSizes(int rcx, int rcy, int rcw, int rch, int skip, bool inter 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)) { - // TODO - this is an estimate of the max distortion relative to the image size. ATM it is hardcoded to be 15%, which seems enough. If not, need to revise - int dW = int (double (parent->fw) * 0.15 / (2 * skip)); - int dH = int (double (parent->fh) * 0.15 / (2 * skip)); - int x1 = orx - dW; - int x2 = orx + orw + dW; - int y1 = ory - dH; - int y2 = ory + orh + dH; + if (parent->ipf.needsTransform(skips(parent->fw, skip), skips(parent->fh, skip), parent->imgsrc->getRotateDegree(), parent->imgsrc->getMetaData())) { + if (check_need_larger_crop_for_lcp_distortion(parent->fw, parent->fh, orx, ory, orw, orh, *parent->params)) { + // TODO - this is an estimate of the max distortion relative to the image size. ATM it is hardcoded to be 15%, which seems enough. If not, need to revise + int dW = int (double (parent->fw) * 0.15 / (2 * skip)); + int dH = int (double (parent->fh) * 0.15 / (2 * skip)); + int x1 = orx - dW; + int x2 = orx + orw + dW; + int y1 = ory - dH; + int y2 = ory + orh + dH; - if (x1 < 0) { - x2 += -x1; - x1 = 0; + if (x1 < 0) { + x2 += -x1; + x1 = 0; + } + + if (x2 > parent->fw) { + x1 -= x2 - parent->fw; + x2 = parent->fw; + } + + if (y1 < 0) { + y2 += -y1; + y1 = 0; + } + + if (y2 > parent->fh) { + y1 -= y2 - parent->fh; + y2 = parent->fh; + } + + orx = max(x1, 0); + ory = max(y1, 0); + orw = min(x2 - x1, parent->fw - orx); + orh = min(y2 - y1, parent->fh - ory); } - - if (x2 > parent->fw) { - x1 -= x2 - parent->fw; - x2 = parent->fw; - } - - if (y1 < 0) { - y2 += -y1; - y1 = 0; - } - - if (y2 > parent->fh) { - y1 -= y2 - parent->fh; - y2 = parent->fh; - } - - orx = max(x1, 0); - ory = max(y1, 0); - orw = min(x2 - x1, parent->fw - orx); - orh = min(y2 - y1, parent->fh - ory); } - leftBorder = skips(rqx1 - bx1, skip); upperBorder = skips(rqy1 - by1, skip); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index a4ca0ea0b..e915a11b0 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -545,7 +545,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) oprevi = orig_prev; // Remove transformation if unneeded - bool needstransform = ipf.needsTransform(); + bool needstransform = ipf.needsTransform(fw, fh, imgsrc->getRotateDegree(), imgsrc->getMetaData()); if ((needstransform || ((todo & (M_TRANSFORM | M_RGBCURVE)) && params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled && !params->colorappearance.enabled))) { assert(oprevi); @@ -1349,7 +1349,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw); ImProcFunctions ipf(&ppar, true); - if (ipf.needsTransform()) { + if (ipf.needsTransform(fW, fH, imgsrc->getRotateDegree(), imgsrc->getMetaData())) { Imagefloat* trImg = new Imagefloat(fW, fH); ipf.transform(im, trImg, 0, 0, 0, 0, fW, fH, fW, fH, imgsrc->getMetaData(), imgsrc->getRotateDegree(), true); diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index c1a4a5979..8f4ae7771 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -119,7 +119,7 @@ public: } void setScale(double iscale); - bool needsTransform() const; + bool needsTransform(int oW, int oH, int rawRotationDeg, const FramesMetaData *metadata) const; bool needsPCVignetting() const; void firstAnalysis(const Imagefloat* const working, const procparams::ProcParams ¶ms, LUTu & vhist16); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index fc79dcae4..c9f88caf0 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -1358,9 +1358,14 @@ bool ImProcFunctions::needsLensfun() const return params->lensProf.useLensfun(); } -bool ImProcFunctions::needsTransform () const +bool ImProcFunctions::needsTransform (int oW, int oH, int rawRotationDeg, const FramesMetaData *metadata) const { - return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsLensfun(); + bool needsLf = needsLensfun(); + if (needsLf) { + std::unique_ptr pLCPMap = LFDatabase::getInstance()->findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg); + needsLf = pLCPMap.get(); + } + return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsLf; } diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 0cdcbf6ed..9da601e2a 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1247,12 +1247,12 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ipf.ToneMapFattal02(baseImg); // perform transform - if (ipf.needsTransform()) { + int origFW; + int origFH; + double tscale = 0.0; + getDimensions (origFW, origFH, tscale); + if (ipf.needsTransform(origFW * tscale + 0.5, origFH * tscale + 0.5, 0, metadata)) { Imagefloat* trImg = new Imagefloat (fw, fh); - int origFW; - int origFH; - double tscale = 0.0; - getDimensions (origFW, origFH, tscale); ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, metadata, 0, true); // Raw rotate degree not detectable here delete baseImg; baseImg = trImg; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 3811c0c80..1c1e46a65 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -872,7 +872,7 @@ private: ipf.ToneMapFattal02(baseImg); // perform transform (excepted resizing) - if (ipf.needsTransform()) { + if (ipf.needsTransform(fw, fh, imgsrc->getRotateDegree(), imgsrc->getMetaData())) { Imagefloat* trImg = nullptr; if (ipf.needsLuminanceOnly()) { trImg = baseImg; From 49d594f67a6f9ad2f2b0d6f0c591136d53fe2dff Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Thu, 2 Jan 2020 19:28:57 +0100 Subject: [PATCH 09/11] Log transform: add method combobox --- rtdata/languages/default | 3 +++ rtengine/iptransform.cc | 4 ++-- rtengine/procparams.cc | 9 ++++++++- rtengine/procparams.h | 1 + rtgui/lensgeom.cc | 40 +++++++++++++++++++++++++++++++++++++--- rtgui/lensgeom.h | 3 +++ rtgui/paramsedited.cc | 6 ++++++ rtgui/paramsedited.h | 1 + 8 files changed, 61 insertions(+), 6 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 5004bf25c..922c50c51 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -787,6 +787,7 @@ HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength HISTORY_MSG_TM_FATTAL_ANCHOR;DRC - Anchor +HISTORY_MSG_TRANS_Method;Geometry - Method HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -1775,6 +1776,8 @@ TP_LABCURVE_RSTPRO_TOOLTIP;Works on the Chromaticity slider and the CC curve. TP_LENSGEOM_AUTOCROP;Auto-Crop TP_LENSGEOM_FILL;Auto-fill TP_LENSGEOM_LABEL;Lens / Geometry +TP_LENSGEOM_LIN;Linear +TP_LENSGEOM_LOG;Logarithmic TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index c9f88caf0..39f270d51 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -1054,7 +1054,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I const double ascale = params->commonTrans.autofill ? getTransformAutoFill(oW, oH, pLCPMap) : 1.0; const bool darkening = (params->vignetting.amount <= 0.0); - const bool useLog = params->pdsharpening.enabled && highQuality; + const bool useLog = params->commonTrans.method == "log" && highQuality; const double centerFactorx = cx - w2; const double centerFactory = cy - h2; @@ -1215,7 +1215,7 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *transformed, int cx, int cy, const LensCorrection *pLCPMap, bool useOriginalBuffer) { assert(pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()); - const bool useLog = params->pdsharpening.enabled; + const bool useLog = params->commonTrans.method == "log"; float** chOrig[3]; chOrig[0] = original->r.ptrs; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index ba6fc237b..99f4f4404 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -1732,13 +1732,14 @@ bool CoarseTransformParams::operator !=(const CoarseTransformParams& other) cons } CommonTransformParams::CommonTransformParams() : + method("log"), autofill(true) { } bool CommonTransformParams::operator ==(const CommonTransformParams& other) const { - return autofill == other.autofill; + return method == other.method && autofill == other.autofill; } bool CommonTransformParams::operator !=(const CommonTransformParams& other) const @@ -3322,6 +3323,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->coarse.vflip, "Coarse Transformation", "VerticalFlip", coarse.vflip, keyFile); // Common properties for transformations + saveToKeyfile(!pedited || pedited->commonTrans.method, "Common Properties for Transformations", "Method", commonTrans.method, keyFile); saveToKeyfile(!pedited || pedited->commonTrans.autofill, "Common Properties for Transformations", "AutoFill", commonTrans.autofill, keyFile); // Rotation @@ -4360,6 +4362,11 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) } if (keyFile.has_group("Common Properties for Transformations")) { + if (keyFile.has_key("Common Properties for Transformations", "Method")) { + assignFromKeyfile(keyFile, "Common Properties for Transformations", "Method", pedited, commonTrans.method, pedited->commonTrans.method); + } else { + commonTrans.method = "lin"; + } assignFromKeyfile(keyFile, "Common Properties for Transformations", "AutoFill", pedited, commonTrans.autofill, pedited->commonTrans.autofill); } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index c41e55872..0b6b2dc46 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -837,6 +837,7 @@ struct CoarseTransformParams { * Common transformation parameters */ struct CommonTransformParams { + Glib::ustring method; bool autofill; CommonTransformParams(); diff --git a/rtgui/lensgeom.cc b/rtgui/lensgeom.cc index 76e0635eb..762726107 100644 --- a/rtgui/lensgeom.cc +++ b/rtgui/lensgeom.cc @@ -17,6 +17,8 @@ * along with RawTherapee. If not, see . */ #include "lensgeom.h" + +#include "eventmapper.h" #include "guiutils.h" #include "rtimage.h" @@ -28,6 +30,18 @@ using namespace rtengine::procparams; LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGEOM_LABEL")), rlistener(nullptr), lastFill(false) { + auto m = ProcEventMapper::getInstance(); + EvTransMethod = m->newEvent(TRANSFORM, "HISTORY_MSG_TRANS_METHOD"); + + Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); + hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); + method = Gtk::manage (new MyComboBoxText ()); + method->append(M("TP_LENSGEOM_LOG")); + method->append(M("TP_LENSGEOM_LIN")); + method->set_active(0); + hb1->pack_end (*method, Gtk::PACK_EXPAND_WIDGET, 4); + pack_start( *hb1, Gtk::PACK_SHRINK, 4); + fill = Gtk::manage (new Gtk::CheckButton (M("TP_LENSGEOM_FILL"))); pack_start (*fill); @@ -39,8 +53,9 @@ LensGeometry::LensGeometry () : FoldableToolPanel(this, "lensgeom", M("TP_LENSGE packBox = Gtk::manage (new ToolParamBlock ()); pack_start (*packBox); - autoCrop->signal_pressed().connect( sigc::mem_fun(*this, &LensGeometry::autoCropPressed) ); - fillConn = fill->signal_toggled().connect( sigc::mem_fun(*this, &LensGeometry::fillPressed) ); + method->connect(method->signal_changed().connect(sigc::mem_fun(*this, &LensGeometry::methodChanged))); + autoCrop->signal_pressed().connect(sigc::mem_fun(*this, &LensGeometry::autoCropPressed)); + fillConn = fill->signal_toggled().connect(sigc::mem_fun(*this, &LensGeometry::fillPressed)); fill->set_active (true); show_all (); @@ -55,8 +70,14 @@ void LensGeometry::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); + method->block (true); + method->set_active(pp->commonTrans.method == "log" ? 0 : 1); if (pedited) { + if(!pedited->commonTrans.method) { + method->set_active_text(M("GENERAL_UNCHANGED")); + } + fill->set_inconsistent (!pedited->commonTrans.autofill); } @@ -67,15 +88,20 @@ void LensGeometry::read (const ProcParams* pp, const ParamsEdited* pedited) lastFill = pp->commonTrans.autofill; + method->block (false); enableListener (); } void LensGeometry::write (ProcParams* pp, ParamsEdited* pedited) { - + int currentRow = method->get_active_row_number(); + if( currentRow >= 0 && method->get_active_text() != M("GENERAL_UNCHANGED")) { + pp->commonTrans.method = currentRow == 0 ? "log" : "lin"; + } pp->commonTrans.autofill = fill->get_active (); if (pedited) { + pedited->commonTrans.method = method->get_active_text() != M("GENERAL_UNCHANGED"); pedited->commonTrans.autofill = !fill->get_inconsistent(); } } @@ -115,6 +141,14 @@ void LensGeometry::fillPressed () } } +void LensGeometry::methodChanged () +{ + + if (listener && method->get_active_row_number() >= 0) { + listener->panelChanged(EvTransMethod, method->get_active_text()); + } +} + void LensGeometry::setBatchMode (bool batchMode) { diff --git a/rtgui/lensgeom.h b/rtgui/lensgeom.h index 18b31a619..73c28b006 100644 --- a/rtgui/lensgeom.h +++ b/rtgui/lensgeom.h @@ -29,6 +29,7 @@ class LensGeometry final : { protected: + MyComboBoxText* method; Gtk::Button* autoCrop; LensGeomListener* rlistener; Gtk::CheckButton* fill; @@ -36,6 +37,7 @@ protected: sigc::connection fillConn; ToolParamBlock* packBox; + rtengine::ProcEvent EvTransMethod; public: LensGeometry (); @@ -50,6 +52,7 @@ public: void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; void setBatchMode (bool batchMode) override; + void methodChanged(); void fillPressed (); void autoCropPressed (); void setLensGeomListener (LensGeomListener* l) diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 82132008a..d41bd472c 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -321,6 +321,7 @@ void ParamsEdited::set(bool v) coarse.rotate = v; coarse.hflip = v; coarse.vflip = v; + commonTrans.method = v; commonTrans.autofill = v; rotate.degree = v; distortion.amount = v; @@ -904,6 +905,7 @@ void ParamsEdited::initFrom(const std::vector& coarse.rotate = coarse.rotate && p.coarse.rotate == other.coarse.rotate; coarse.hflip = coarse.hflip && p.coarse.hflip == other.coarse.hflip; coarse.vflip = coarse.vflip && p.coarse.vflip == other.coarse.vflip; + commonTrans.method = commonTrans.method && p.commonTrans.method == other.commonTrans.method; commonTrans.autofill = commonTrans.autofill && p.commonTrans.autofill == other.commonTrans.autofill; rotate.degree = rotate.degree && p.rotate.degree == other.rotate.degree; distortion.amount = distortion.amount && p.distortion.amount == other.distortion.amount; @@ -2265,6 +2267,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.coarse.vflip = mods.coarse.vflip; } + if (commonTrans.method) { + toEdit.commonTrans.method = mods.commonTrans.method; + } + if (commonTrans.autofill) { toEdit.commonTrans.autofill = mods.commonTrans.autofill; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 01a3e4efe..153dd7bb6 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -365,6 +365,7 @@ struct CoarseTransformParamsEdited { }; struct CommonTransformParamsEdited { + bool method; bool autofill; }; From e07ff4032b23198d6cd33717888ab8484d895744 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Fri, 3 Jan 2020 11:35:20 +0100 Subject: [PATCH 10/11] log transform: Fix segfault --- rtengine/iptransform.cc | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 39f270d51..29e10035e 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -1217,15 +1217,7 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans assert(pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable()); const bool useLog = params->commonTrans.method == "log"; - float** chOrig[3]; - chOrig[0] = original->r.ptrs; - chOrig[1] = original->g.ptrs; - chOrig[2] = original->b.ptrs; - - float** chTrans[3]; - chTrans[0] = transformed->r.ptrs; - chTrans[1] = transformed->g.ptrs; - chTrans[2] = transformed->b.ptrs; + float** chTrans[3] = {transformed->r.ptrs, transformed->g.ptrs, transformed->b.ptrs}; std::unique_ptr tempLog; if (useLog) { @@ -1237,6 +1229,7 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans logEncode(original, original, multiThread); } } + float** chOrig[3] = {original->r.ptrs, original->g.ptrs, original->b.ptrs}; #ifdef _OPENMP #pragma omp parallel for if (multiThread) @@ -1276,7 +1269,7 @@ void ImProcFunctions::transformLCPCAOnly(Imagefloat *original, Imagefloat *trans if (!useLog) { chTrans[c][y][x] = (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); } else { - chTrans[c][y][x] = (chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); + chTrans[c][y][x] = xexpf(chOrig[c][y1][x1] * (1.0 - Dx) * (1.0 - Dy) + chOrig[c][y1][x2] * Dx * (1.0 - Dy) + chOrig[c][y2][x1] * (1.0 - Dx) * Dy + chOrig[c][y2][x2] * Dx * Dy); } } } else { From 0edac2dac752ad75656817140b8492812ab2dd4d Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Mon, 6 Jan 2020 19:01:30 +0100 Subject: [PATCH 11/11] Speedup for scalar xlog functions --- rtengine/sleef.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rtengine/sleef.h b/rtengine/sleef.h index 1a953953c..b7655258b 100644 --- a/rtengine/sleef.h +++ b/rtengine/sleef.h @@ -532,7 +532,7 @@ __inline double xlog(double d) { x = x * t + 0.693147180559945286226764 * e; - if (xisinf(d)) x = rtengine::RT_INFINITY; + if (xispinf(d)) x = rtengine::RT_INFINITY; if (d < 0) x = rtengine::RT_NAN; if (d == 0) x = -rtengine::RT_INFINITY; @@ -864,7 +864,7 @@ __inline double xlog10(double a) { double2 d = mul_dd(logk(a), dd(0.43429448190325176116, 6.6494347733425473126e-17)); double x = d.x + d.y; - if (xisinf(a)) x = rtengine::RT_INFINITY; + if (xispinf(a)) x = rtengine::RT_INFINITY; if (a < 0) x = rtengine::RT_NAN; if (a == 0) x = -rtengine::RT_INFINITY; @@ -875,7 +875,7 @@ __inline double xlog1p(double a) { double2 d = logk2(add2_ss(a, 1)); double x = d.x + d.y; - if (xisinf(a)) x = rtengine::RT_INFINITY; + if (xispinf(a)) x = rtengine::RT_INFINITY; if (a < -1) x = rtengine::RT_NAN; if (a == -1) x = -rtengine::RT_INFINITY; @@ -1208,7 +1208,7 @@ __inline float xlogf(float d) { x = x * t + 0.693147180559945286226764f * e; - if (xisinff(d)) x = rtengine::RT_INFINITY_F; + if (xispinff(d)) x = rtengine::RT_INFINITY_F; if (d < 0) x = rtengine::RT_NAN_F; if (d == 0) x = -rtengine::RT_INFINITY_F; @@ -1233,7 +1233,7 @@ __inline float xlogf1(float d) { // does xlogf(vmaxf(d, 1.f)) but faster x = x * t + 0.693147180559945286226764f * e; - if (xisinff(d)) x = rtengine::RT_INFINITY_F; + if (xispinff(d)) x = rtengine::RT_INFINITY_F; if (d <= 1.f) x = 0; return x;