Capture sharpening: minor speedups

This commit is contained in:
Ingo Weyrich
2020-01-12 19:36:37 +01:00
parent 01fbc2eddf
commit 54bce4af64

View File

@@ -26,7 +26,7 @@
#include "procparams.h" #include "procparams.h"
#include "color.h" #include "color.h"
#include "rt_algo.h" #include "rt_algo.h"
//#define BENCHMARK #define BENCHMARK
#include "StopWatch.h" #include "StopWatch.h"
#include "opthelper.h" #include "opthelper.h"
#include "../rtgui/multilangmgr.h" #include "../rtgui/multilangmgr.h"
@@ -525,28 +525,25 @@ float calcRadiusXtrans(const float * const *rawData, int W, int H, float lowerLi
bool checkForStop(float** tmpIThr, float** iterCheck, int fullTileSize, int border) bool checkForStop(float** tmpIThr, float** iterCheck, int fullTileSize, int border)
{ {
bool stopped = false; for (int ii = border; ii < fullTileSize - border; ++ii) {
for (int ii = border; !stopped && ii < fullTileSize - border; ++ii) {
#ifdef __SSE2__ #ifdef __SSE2__
for (int jj = border; jj < fullTileSize - border; jj += 4) { for (int jj = border; jj < fullTileSize - border; jj += 4) {
if (_mm_movemask_ps((vfloat)vmaskf_lt(LVFU(tmpIThr[ii][jj]), LVFU(iterCheck[ii - border][jj - border])))) { if (UNLIKELY(_mm_movemask_ps((vfloat)vmaskf_lt(LVFU(tmpIThr[ii][jj]), LVFU(iterCheck[ii - border][jj - border]))))) {
stopped = true; return true;
break;
} }
} }
#else #else
for (int jj = border; jj < fullTileSize - border; ++jj) { for (int jj = border; jj < fullTileSize - border; ++jj) {
if (tmpIThr[ii][jj] < iterCheck[ii - border][jj - border]) { if (tmpIThr[ii][jj] < iterCheck[ii - border][jj - border]) {
stopped = true; return true;
break;
} }
} }
#endif #endif
} }
return stopped; return false;
} }
void CaptureDeconvSharpening (float ** clipmask, float** luminance, float** oldLuminance, const float * const * blend, int W, int H, double sigma, double sigmaCornerOffset, int iterations, bool checkIterStop, rtengine::ProgressListener* plistener, double startVal, double endVal) void CaptureDeconvSharpening (float** luminance, const float* const * oldLuminance, const float * const * blend, int W, int H, double sigma, double sigmaCornerOffset, int iterations, bool checkIterStop, rtengine::ProgressListener* plistener, double startVal, double endVal)
{ {
BENCHFUN BENCHFUN
const bool is5x5 = (sigma <= 0.84 && sigmaCornerOffset == 0.0); const bool is5x5 = (sigma <= 0.84 && sigmaCornerOffset == 0.0);
@@ -571,6 +568,7 @@ BENCHFUN
double progress = startVal; double progress = startVal;
const double progressStep = (endVal - startVal) * rtengine::SQR(tileSize) / (W * H); const double progressStep = (endVal - startVal) * rtengine::SQR(tileSize) / (W * H);
constexpr float minBlend = 0.01f; constexpr float minBlend = 0.01f;
#ifdef _OPENMP #ifdef _OPENMP
@@ -597,14 +595,14 @@ BENCHFUN
if (checkIterStop) { if (checkIterStop) {
for (int k = 0, ii = endOfCol ? H - fullTileSize + border : i; k < tileSize; ++k, ++ii) { for (int k = 0, ii = endOfCol ? H - fullTileSize + border : i; k < tileSize; ++k, ++ii) {
for (int l = 0, jj = endOfRow ? W - fullTileSize + border : j; l < tileSize; ++l, ++jj) { for (int l = 0, jj = endOfRow ? W - fullTileSize + border : j; l < tileSize; ++l, ++jj) {
iterCheck[k][l] = oldLuminance[ii][jj] * clipmask[ii][jj] * 0.5f; iterCheck[k][l] = oldLuminance[ii][jj] * blend[ii][jj] * 0.5f;
maxVal = std::max(maxVal, clipmask[ii][jj]); maxVal = std::max(maxVal, blend[ii][jj]);
} }
} }
} else { } else {
for (int k = 0, ii = endOfCol ? H - fullTileSize + border : i; k < tileSize; ++k, ++ii) { for (int k = 0, ii = endOfCol ? H - fullTileSize + border : i; k < tileSize; ++k, ++ii) {
for (int l = 0, jj = endOfRow ? W - fullTileSize + border : j; l < tileSize; ++l, ++jj) { for (int l = 0, jj = endOfRow ? W - fullTileSize + border : j; l < tileSize; ++l, ++jj) {
maxVal = std::max(maxVal, clipmask[ii][jj]); maxVal = std::max(maxVal, blend[ii][jj]);
} }
} }
} }
@@ -623,14 +621,14 @@ BENCHFUN
if (checkIterStop) { if (checkIterStop) {
for (int ii = 0; ii < tileSize; ++ii) { for (int ii = 0; ii < tileSize; ++ii) {
for (int jj = 0; jj < tileSize; ++jj) { for (int jj = 0; jj < tileSize; ++jj) {
iterCheck[ii][jj] = oldLuminance[i + ii][j + jj] * clipmask[i + ii][j + jj] * 0.5f; iterCheck[ii][jj] = oldLuminance[i + ii][j + jj] * blend[i + ii][j + jj] * 0.5f;
maxVal = std::max(maxVal, clipmask[i + ii][j + jj]); maxVal = std::max(maxVal, blend[i + ii][j + jj]);
} }
} }
} else { } else {
for (int ii = 0; ii < tileSize; ++ii) { for (int ii = 0; ii < tileSize; ++ii) {
for (int jj = 0; jj < tileSize; ++jj) { for (int jj = 0; jj < tileSize; ++jj) {
maxVal = std::max(maxVal, clipmask[i + ii][j + jj]); maxVal = std::max(maxVal, blend[i + ii][j + jj]);
} }
} }
} }
@@ -645,23 +643,22 @@ BENCHFUN
} }
} }
} }
bool stopped = false;
if (is3x3) { if (is3x3) {
for (int k = 0; k < iterations && !stopped; ++k) { for (int k = 0; k < iterations; ++k) {
// apply 3x3 gaussian blur and divide luminance by result of gaussian blur // apply 3x3 gaussian blur and divide luminance by result of gaussian blur
gauss3x3div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel3); gauss3x3div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel3);
gauss3x3mult(tmpThr, tmpIThr, fullTileSize, kernel3); gauss3x3mult(tmpThr, tmpIThr, fullTileSize, kernel3);
if (checkIterStop) { if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border); break;
} }
} }
} else if (is5x5) { } else if (is5x5) {
for (int k = 0; k < iterations && !stopped; ++k) { for (int k = 0; k < iterations; ++k) {
// apply 5x5 gaussian blur and divide luminance by result of gaussian blur // apply 5x5 gaussian blur and divide luminance by result of gaussian blur
gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel5); gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel5);
gauss5x5mult(tmpThr, tmpIThr, fullTileSize, kernel5); gauss5x5mult(tmpThr, tmpIThr, fullTileSize, kernel5);
if (checkIterStop) { if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border); break;
} }
} }
} else { } else {
@@ -672,34 +669,34 @@ BENCHFUN
if (sigmaTile > 0.84) { // have to use 7x7 kernel if (sigmaTile > 0.84) { // have to use 7x7 kernel
float lkernel7[7][7]; float lkernel7[7][7];
compute7x7kernel(static_cast<float>(sigma) + distanceFactor * distance, lkernel7); compute7x7kernel(static_cast<float>(sigma) + distanceFactor * distance, lkernel7);
for (int k = 0; k < iterations && !stopped; ++k) { for (int k = 0; k < iterations; ++k) {
// apply 7x7 gaussian blur and divide luminance by result of gaussian blur // apply 7x7 gaussian blur and divide luminance by result of gaussian blur
gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel7); gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel7);
gauss7x7mult(tmpThr, tmpIThr, fullTileSize, lkernel7); gauss7x7mult(tmpThr, tmpIThr, fullTileSize, lkernel7);
if (checkIterStop) { if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border); break;
} }
} }
} else { // can use 5x5 kernel } else { // can use 5x5 kernel
float lkernel7[5][5]; float lkernel5[5][5];
compute5x5kernel(static_cast<float>(sigma) + distanceFactor * distance, lkernel7); compute5x5kernel(static_cast<float>(sigma) + distanceFactor * distance, lkernel5);
for (int k = 0; k < iterations && !stopped; ++k) { for (int k = 0; k < iterations; ++k) {
// apply 7x7 gaussian blur and divide luminance by result of gaussian blur // apply 7x7 gaussian blur and divide luminance by result of gaussian blur
gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel7); gauss5x5div(tmpIThr, tmpThr, lumThr, fullTileSize, lkernel5);
gauss5x5mult(tmpThr, tmpIThr, fullTileSize, lkernel7); gauss5x5mult(tmpThr, tmpIThr, fullTileSize, lkernel5);
if (checkIterStop) { if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border); break;
} }
} }
} }
} }
} else { } else {
for (int k = 0; k < iterations && !stopped; ++k) { for (int k = 0; k < iterations; ++k) {
// apply 7x7 gaussian blur and divide luminance by result of gaussian blur // apply 7x7 gaussian blur and divide luminance by result of gaussian blur
gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel7); gauss7x7div(tmpIThr, tmpThr, lumThr, fullTileSize, kernel7);
gauss7x7mult(tmpThr, tmpIThr, fullTileSize, kernel7); gauss7x7mult(tmpThr, tmpIThr, fullTileSize, kernel7);
if (checkIterStop) { if (checkIterStop && k < iterations - 1 && checkForStop(tmpIThr, iterCheck, fullTileSize, border)) {
stopped = checkForStop(tmpIThr, iterCheck, fullTileSize, border); break;
} }
} }
} }
@@ -719,12 +716,12 @@ BENCHFUN
} }
} }
if (plistener) { if (plistener) {
if (++progresscounter % 16 == 0) { if (++progresscounter % 32 == 0) {
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp critical(csprogress) #pragma omp critical(csprogress)
#endif #endif
{ {
progress += 16.0 * progressStep; progress += 32.0 * progressStep;
progress = rtengine::min(progress, endVal); progress = rtengine::min(progress, endVal);
plistener->setProgress(progress); plistener->setProgress(progress);
} }
@@ -751,6 +748,7 @@ void RawImageSource::captureSharpening(const procparams::CaptureSharpeningParams
plistener->setProgress(0.0); plistener->setProgress(0.0);
} }
BENCHFUN BENCHFUN
constexpr float xyz_rgb[3][3] = { // XYZ from RGB constexpr float xyz_rgb[3][3] = { // XYZ from RGB
{ 0.412453, 0.357580, 0.180423 }, { 0.412453, 0.357580, 0.180423 },
{ 0.212671, 0.715160, 0.072169 }, { 0.212671, 0.715160, 0.072169 },
@@ -829,8 +827,7 @@ BENCHFUN
plistener->setProgress(0.1); plistener->setProgress(0.1);
} }
array2D<float>& blend = red; // red will be overridden anyway => we can use its buffer to store the blend mask buildBlendMask(L, clipMask, W, H, contrast, sharpeningParams.autoContrast, clipMask);
buildBlendMask(L, blend, W, H, contrast, sharpeningParams.autoContrast, clipMask);
if (plistener) { if (plistener) {
plistener->setProgress(0.2); plistener->setProgress(0.2);
} }
@@ -840,7 +837,7 @@ BENCHFUN
#endif #endif
for (int i = 0; i < H; ++i) { for (int i = 0; i < H; ++i) {
for (int j = 0; j < W; ++j) { for (int j = 0; j < W; ++j) {
red[i][j] = green[i][j] = blue[i][j] = blend[i][j] * 16384.f; red[i][j] = green[i][j] = blue[i][j] = clipMask[i][j] * 16384.f;
} }
} }
if (plistener) { if (plistener) {
@@ -877,18 +874,18 @@ BENCHFUN
if (plistener) { if (plistener) {
plistener->setProgress(0.1); plistener->setProgress(0.1);
} }
// calculate contrast based blend factors to reduce sharpening in regions with low contrast // calculate contrast based blend factors to reduce sharpening in regions with low contrast
array2D<float>& blend = clipMask; // we can share blend and clipMask buffer here buildBlendMask(L, clipMask, W, H, contrast, sharpeningParams.autoContrast, clipMask);
buildBlendMask(L, blend, W, H, contrast, sharpeningParams.autoContrast, clipMask);
if (plistener) { if (plistener) {
plistener->setProgress(0.2); plistener->setProgress(0.2);
} }
conrastThreshold = contrast * 100.f; conrastThreshold = contrast * 100.f;
CaptureDeconvSharpening(YNew, YOld, clipMask, W, H, radius, sharpeningParams.deconvradiusOffset, sharpeningParams.deconviter, sharpeningParams.deconvitercheck, plistener, 0.2, 0.9);
CaptureDeconvSharpening(clipMask, YNew, YOld, blend, W, H, radius, sharpeningParams.deconvradiusOffset, sharpeningParams.deconviter, sharpeningParams.deconvitercheck, plistener, 0.2, 0.9);
if (plistener) { if (plistener) {
plistener->setProgress(0.9); plistener->setProgress(0.9);
} }
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 16) #pragma omp parallel for schedule(dynamic, 16)
#endif #endif
@@ -896,7 +893,7 @@ BENCHFUN
int j = 0; int j = 0;
#ifdef __SSE2__ #ifdef __SSE2__
for (; j < W - 3; j += 4) { for (; j < W - 3; j += 4) {
const vfloat factor = vmaxf(LVFU(YNew[i][j]), ZEROV) / vmaxf(LVFU(YOld[i][j]), F2V(0.00001f)); const vfloat factor = LVFU(YNew[i][j]) / vmaxf(LVFU(YOld[i][j]), F2V(0.00001f));
STVFU(red[i][j], LVFU(redVals[i][j]) * factor); STVFU(red[i][j], LVFU(redVals[i][j]) * factor);
STVFU(green[i][j], LVFU(greenVals[i][j]) * factor); STVFU(green[i][j], LVFU(greenVals[i][j]) * factor);
STVFU(blue[i][j], LVFU(blueVals[i][j]) * factor); STVFU(blue[i][j], LVFU(blueVals[i][j]) * factor);
@@ -904,7 +901,7 @@ BENCHFUN
#endif #endif
for (; j < W; ++j) { for (; j < W; ++j) {
const float factor = std::max(YNew[i][j], 0.f) / std::max(YOld[i][j], 0.00001f); const float factor = YNew[i][j] / std::max(YOld[i][j], 0.00001f);
red[i][j] = redVals[i][j] * factor; red[i][j] = redVals[i][j] * factor;
green[i][j] = greenVals[i][j] * factor; green[i][j] = greenVals[i][j] * factor;
blue[i][j] = blueVals[i][j] * factor; blue[i][j] = blueVals[i][j] * factor;