diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 3ae8f1d65..e2b4d2002 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -42,7 +42,7 @@ extern const Settings* settings; Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow) : PipetteBuffer (editDataProvider), origCrop (nullptr), laboCrop (nullptr), labnCrop (nullptr), - cropImg (nullptr), cbuf_real (nullptr), transCrop (nullptr), cieCrop (nullptr), cbuffer (nullptr), + cropImg (nullptr), transCrop (nullptr), cieCrop (nullptr), updating (false), newUpdatePending (false), skip (10), cropx (0), cropy (0), cropw (-1), croph (-1), trafx (0), trafy (0), trafw (-1), trafh (-1), @@ -865,7 +865,7 @@ void Crop::update (int todo) if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { parent->ipf.MLmicrocontrast (labnCrop); - parent->ipf.sharpening (labnCrop, (float**)cbuffer, params.sharpening); + parent->ipf.sharpening (labnCrop, params.sharpening); } } @@ -1082,16 +1082,6 @@ void Crop::freeAll () cieCrop = nullptr; } - if (cbuf_real) { - delete [] cbuf_real; - cbuf_real = nullptr; - } - - if (cbuffer ) { - delete [] cbuffer; - cbuffer = nullptr; - } - PipetteBuffer::flush(); } @@ -1269,21 +1259,6 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte cieCrop = nullptr; } - if (cbuffer ) { - delete [] cbuffer; - } - - if (cbuf_real) { - delete [] cbuf_real; - } - - cbuffer = new float*[croph]; - cbuf_real = new float[ (croph + 2)*cropw]; - - for (int i = 0; i < croph; i++) { - cbuffer[i] = cbuf_real + cropw * i + cropw; - } - if (editType == ET_PIPETTE) { PipetteBuffer::resize (cropw, croph); } else if (PipetteBuffer::bufferCreated()) { diff --git a/rtengine/dcrop.h b/rtengine/dcrop.h index 7ec346d3c..efd4a399a 100644 --- a/rtengine/dcrop.h +++ b/rtengine/dcrop.h @@ -44,13 +44,11 @@ protected: LabImage* laboCrop; // "one chunk" allocation LabImage* labnCrop; // "one chunk" allocation Image8* cropImg; // "one chunk" allocation ; displayed image in monitor color space, showing the output profile as well (soft-proofing enabled, which then correspond to workimg) or not - float * cbuf_real; // "one chunk" allocation // --- automatically allocated and deleted when necessary, and only renewed on size changes Imagefloat* transCrop; // "one chunk" allocation, allocated if necessary CieImage* cieCrop; // allocating 6 images, each in "one chunk" allocation // ----------------------------------------------------------------- - float** cbuffer; bool updating; /// Flag telling if an updater thread is currently processing bool newUpdatePending; /// Flag telling the updater thread that a new update is pending diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 135ab26ee..78f0c5b9e 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -226,7 +226,7 @@ public: void chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf &acurve, LUTf &bcurve, LUTf & satcurve, LUTf & satclcurve, LUTf &clcurve, LUTf &curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histLurve); void vibrance (LabImage* lab);//Jacques' vibrance // void colorCurve (LabImage* lold, LabImage* lnew); - void sharpening (LabImage* lab, float** buffer, SharpeningParams &sharpenParam); + void sharpening (LabImage* lab, const SharpeningParams &sharpenParam); void sharpeningcam (CieImage* ncie, float** buffer); 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); float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh); diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc index 2779beb08..94b2b110c 100644 --- a/rtengine/ipsharpen.cc +++ b/rtengine/ipsharpen.cc @@ -24,17 +24,19 @@ #include "rt_math.h" #include "sleef.c" #include "opthelper.h" -//#define BENCHMARK +#define BENCHMARK #include "StopWatch.h" using namespace std; namespace { + float calcBlendFactor(float val, float threshold) { // sigmoid function // result is in ]0;1] range // inflexion point is at (x, y) (threshold, 0.5) return threshold == 0.f ? 1.f : 1.f / (1.f + xexpf(16.f - 16.f * val / threshold)); } + #ifdef __SSE2__ vfloat calcBlendFactor(vfloat valv, vfloat thresholdv) { // sigmoid function @@ -48,31 +50,33 @@ vfloat calcBlendFactor(vfloat valv, vfloat thresholdv) { #endif void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int W, int H, float contrastThreshold, float amount = 1.f) { +BENCHFUN // upper border for(int j = 0; j < 2; j++) for(int i = 0; i < W; ++i) { blend[j][i] = 0.f; } + constexpr float scale = 0.0625f / 327.68f; #ifdef _OPENMP #pragma omp parallel #endif { #ifdef __SSE2__ - vfloat contrastThresholdv = F2V(contrastThreshold); - vfloat scalev = F2V(0.0625f / 327.68f); - vfloat amountv = F2V(amount); + const vfloat contrastThresholdv = F2V(contrastThreshold); + const vfloat scalev = F2V(scale); + const vfloat amountv = F2V(amount); #endif #ifdef _OPENMP #pragma omp for schedule(dynamic,16) nowait #endif for(int j = 2; j < H - 2; ++j) { + // left two pixels blend[j][0] = blend[j][1] = 0.f; int i = 2; #ifdef __SSE2__ for(; i < W - 5; i += 4) { - vfloat contrastv = vsqrtf(SQRV(LVFU(luminance[j][i+1]) - LVFU(luminance[j][i-1])) + SQRV(LVFU(luminance[j+1][i]) - LVFU(luminance[j-1][i])) + SQRV(LVFU(luminance[j][i+2]) - LVFU(luminance[j][i-2])) + SQRV(LVFU(luminance[j+2][i]) - LVFU(luminance[j-2][i]))) * scalev; @@ -82,10 +86,11 @@ void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int for(; i < W - 2; ++i) { float contrast = sqrtf(SQR(luminance[j][i+1] - luminance[j][i-1]) + SQR(luminance[j+1][i] - luminance[j-1][i]) + - SQR(luminance[j][i+2] - luminance[j][i-2]) + SQR(luminance[j+2][i] - luminance[j-2][i])) * 0.0625f / 327.68f; + SQR(luminance[j][i+2] - luminance[j][i-2]) + SQR(luminance[j+2][i] - luminance[j-2][i])) * scale; blend[j][i] = amount * calcBlendFactor(contrast, contrastThreshold); } + // right two pixels blend[j][W - 2] = blend[j][W - 1] = 0.f; } #ifdef _OPENMP @@ -98,14 +103,17 @@ void buildBlendMask(float** luminance, rtengine::JaggedArray &blend, int blend[j][i] = 0.f; } } + // blur blend mask to smooth transitions + gaussianBlur(blend, blend, W, H, 2.0); + } } void sharpenHaloCtrl (float** luminance, float** blurmap, float** base, float** blend, int W, int H, const SharpeningParams &sharpenParam) { - float scale = (100.f - sharpenParam.halocontrol_amount) * 0.01f; - float sharpFac = sharpenParam.amount * 0.01f; + const float scale = (100.f - sharpenParam.halocontrol_amount) * 0.01f; + const float sharpFac = sharpenParam.amount * 0.01f; float** nL = base; #ifdef _OPENMP @@ -170,12 +178,12 @@ void dcdamping (float** aI, float** aO, float damping, int W, int H) const float dampingFac = -2.0 / (damping * damping); #ifdef __SSE2__ - __m128 Iv, Ov, Uv, zerov, onev, fourv, fivev, dampingFacv, Tv, Wv, Lv; - zerov = _mm_setzero_ps( ); - onev = F2V( 1.0f ); - fourv = F2V( 4.0f ); - fivev = F2V( 5.0f ); - dampingFacv = F2V( dampingFac ); + vfloat Iv, Ov, Uv, zerov, onev, fourv, fivev, dampingFacv, Tv, Wv, Lv; + zerov = _mm_setzero_ps(); + onev = F2V(1.f); + fourv = F2V(4.f); + fivev = F2V(5.f); + dampingFacv = F2V(dampingFac); #endif #ifdef _OPENMP #pragma omp for @@ -186,8 +194,8 @@ void dcdamping (float** aI, float** aO, float damping, int W, int H) #ifdef __SSE2__ for (; j < W - 3; j += 4) { - Iv = LVFU( aI[i][j] ); - Ov = LVFU( aO[i][j] ); + Iv = LVFU(aI[i][j]); + Ov = LVFU(aO[i][j]); Lv = xlogf(Iv / Ov); Wv = Ov - Iv; Uv = (Ov * Lv + Wv) * dampingFacv; @@ -198,7 +206,7 @@ void dcdamping (float** aI, float** aO, float damping, int W, int H) Uv = (Wv / Iv) * Uv + onev; Uv = vselfzero(vmaskf_gt(Iv, zerov), Uv); Uv = vselfzero(vmaskf_gt(Ov, zerov), Uv); - STVFU( aI[i][j], Uv ); + STVFU(aI[i][j], Uv); } #endif @@ -221,6 +229,7 @@ void dcdamping (float** aI, float** aO, float damping, int W, int H) } } + namespace rtengine { @@ -247,9 +256,9 @@ BENCHFUN JaggedArray blend(W, H); buildBlendMask(luminance, blend, W, H, sharpenParam.contrast / 100.f, sharpenParam.deconvamount / 100.0); - float damping = sharpenParam.deconvdamping / 5.0; - bool needdamp = sharpenParam.deconvdamping > 0; - double sigma = sharpenParam.deconvradius / scale; + const float damping = sharpenParam.deconvdamping / 5.0; + const bool needdamp = sharpenParam.deconvdamping > 0; + const double sigma = sharpenParam.deconvradius / scale; #ifdef _OPENMP #pragma omp parallel @@ -289,20 +298,23 @@ BENCHFUN } // end parallel } -void ImProcFunctions::sharpening (LabImage* lab, float** b2, SharpeningParams &sharpenParam) +void ImProcFunctions::sharpening (LabImage* lab, const SharpeningParams &sharpenParam) { if ((!sharpenParam.enabled) || sharpenParam.amount < 1 || lab->W < 8 || lab->H < 8) { return; } + int W = lab->W, H = lab->H; + JaggedArray b2(W, H); + if (sharpenParam.method == "rld") { deconvsharpening (lab->L, b2, lab->W, lab->H, sharpenParam); return; } + // Rest is UNSHARP MASK - int W = lab->W, H = lab->H; float** b3 = nullptr; if (sharpenParam.edgesonly) { diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 6a59241e1..7818871a7 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1053,20 +1053,8 @@ private: } if (((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) && params.sharpening.enabled) { + ipf.sharpening (labView, params.sharpening); - float **buffer = new float*[fh]; - - for (int i = 0; i < fh; i++) { - buffer[i] = new float[fw]; - } - - ipf.sharpening (labView, (float**)buffer, params.sharpening); - - for (int i = 0; i < fh; i++) { - delete [] buffer[i]; - } - - delete [] buffer; } WaveletParams WaveParams = params.wavelet; @@ -1165,7 +1153,7 @@ private: int imw, imh; double tmpScale = ipf.resizeScale (¶ms, fw, fh, imw, imh); - bool labResize = params.resize.enabled && params.resize.method != "Nearest" && tmpScale != 1.0; + bool labResize = params.resize.enabled && params.resize.method != "Nearest" && (tmpScale != 1.0 || params.prsharpening.enabled); LabImage *tmplab; // crop and convert to rgb16 @@ -1196,33 +1184,23 @@ private: } if (labResize) { // resize lab data - // resize image - tmplab = new LabImage (imw, imh); - ipf.Lanczos (labView, tmplab, tmpScale); - delete labView; - labView = tmplab; + if(labView->W != imw || labView->H != imh) { + // resize image + tmplab = new LabImage (imw, imh); + ipf.Lanczos (labView, tmplab, tmpScale); + delete labView; + labView = tmplab; + } cw = labView->W; ch = labView->H; if (params.prsharpening.enabled) { - for (int i = 0; i < ch; i++) + for (int i = 0; i < ch; i++) { for (int j = 0; j < cw; j++) { labView->L[i][j] = labView->L[i][j] < 0.f ? 0.f : labView->L[i][j]; } - - float **buffer = new float*[ch]; - - for (int i = 0; i < ch; i++) { - buffer[i] = new float[cw]; } - - ipf.sharpening (labView, (float**)buffer, params.prsharpening); - - for (int i = 0; i < ch; i++) { - delete [] buffer[i]; - } - - delete [] buffer; + ipf.sharpening (labView, params.prsharpening); } }