Local adjustment denoise - added Laplacian to detail threshold DCT (#6027)

* Comment code

* Change GUI place edge detection

* added usemask in reset

* Added sk gaussian blur edge DCT

* Improve Laplacian threshold detail DCT
This commit is contained in:
Desmis 2020-12-19 07:46:12 +01:00 committed by GitHub
parent 183b20110b
commit 36cd2bc8ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1017 additions and 54 deletions

View File

@ -1229,7 +1229,7 @@ HISTORY_MSG_981;Local - Log encoding Strength
HISTORY_MSG_982;Local - Equalizer hue
HISTORY_MSG_983;Local - denoise threshold mask high
HISTORY_MSG_984;Local - denoise threshold mask low
HISTORY_MSG_985;Local - denoise use mask
HISTORY_MSG_985;Local - denoise Laplacian
HISTORY_MSG_986;Local - denoise reinforce
HISTORY_MSG_BLSHAPE;Blur by level
HISTORY_MSG_BLURCWAV;Blur chroma
@ -2559,6 +2559,7 @@ TP_LOCALLAB_DENOI_EXP;Denoise
TP_LOCALLAB_DENOI_TOOLTIP;This module can be used for noise reduction either on its own (at the end of the processing pipeline) or in addition to the Noise Reduction module in the Detail tab (which works at the beginning of the pipeline).\n Scope allows you to differentiate the action based on color (deltaE).\n\n You can refine the result with a "Median filter" or a "Guided Filter" (Soft radius).
TP_LOCALLAB_DEPTH;Depth
TP_LOCALLAB_DETAIL;Local contrast
TP_LOCALLAB_DETAILFRA;Edge detection
TP_LOCALLAB_DETAILSH;Details
TP_LOCALLAB_DETAILTHR;Luminance & chroma detail threshold (DCT ƒ)
TP_LOCALLAB_DUPLSPOTNAME;Copy
@ -3024,7 +3025,7 @@ TP_LOCALLAB_TRANSIT_TOOLTIP;Adjust smoothness of transition between affected and
TP_LOCALLAB_TRANSMISSIONGAIN;Transmission gain
TP_LOCALLAB_TRANSMISSIONMAP;Transmission map
TP_LOCALLAB_TRANSMISSION_TOOLTIP;Transmission according to transmission.\nAbscissa: transmission from negative values (min), mean, and positive values (max).\nOrdinate: amplification or reduction.\nYou can adjust this curve to change the Transmission and reduce artifacts
//TP_LOCALLAB_USEMASK;Use mask
TP_LOCALLAB_USEMASK;Laplacian
TP_LOCALLAB_VART;Variance (contrast)
TP_LOCALLAB_VIBRANCE;Vibrance & Warm/Cool
TP_LOCALLAB_VIBRA_TOOLTIP;Adjusts vibrance (essentially the same as the global adjustment).\nCarries out the equivalent of a white-balance adjustment using a CIECAM algorithm.

889
rtengine/boxblural.h Normal file
View File

@ -0,0 +1,889 @@
/* -*- C++ -*-
*
* This file is part of RawTherapee.
*
* Copyright (C) 2010 Emil Martinec <ejmartin@uchicago.edu>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BOXBLURAL_H_
#define _BOXBLURAL_H_
#include <assert.h>
#include <memory>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "alignedbuffer.h"
#include "rt_math.h"
#include "opthelper.h"
#include "StopWatch.h"
namespace rtengine
{
// classical filtering if the support window is small:
template<class T, class A> void boxblur (T** src, A** dst, int radx, int rady, int W, int H)
{
//box blur image; box range = (radx,rady)
assert(2*radx+1 < W);
assert(2*rady+1 < H);
AlignedBuffer<float>* buffer = new AlignedBuffer<float> (W * H);
float* temp = buffer->data;
if (radx == 0) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int row = 0; row < H; row++)
for (int col = 0; col < W; col++) {
temp[row * W + col] = (float)src[row][col];
}
} else {
//horizontal blur
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int row = 0; row < H; row++) {
int len = radx + 1;
temp[row * W + 0] = (float)src[row][0] / len;
for (int j = 1; j <= radx; j++) {
temp[row * W + 0] += (float)src[row][j] / len;
}
for (int col = 1; col <= radx; col++) {
temp[row * W + col] = (temp[row * W + col - 1] * len + (float)src[row][col + radx]) / (len + 1);
len ++;
}
for (int col = radx + 1; col < W - radx; col++) {
temp[row * W + col] = temp[row * W + col - 1] + ((float)(src[row][col + radx] - src[row][col - radx - 1])) / len;
}
for (int col = W - radx; col < W; col++) {
temp[row * W + col] = (temp[row * W + col - 1] * len - src[row][col - radx - 1]) / (len - 1);
len --;
}
}
}
if (rady == 0) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int row = 0; row < H; row++)
for (int col = 0; col < W; col++) {
dst[row][col] = temp[row * W + col];
}
} else {
//vertical blur
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int col = 0; col < W; col++) {
int len = rady + 1;
dst[0][col] = temp[0 * W + col] / len;
for (int i = 1; i <= rady; i++) {
dst[0][col] += temp[i * W + col] / len;
}
for (int row = 1; row <= rady; row++) {
dst[row][col] = (dst[(row - 1)][col] * len + temp[(row + rady) * W + col]) / (len + 1);
len ++;
}
for (int row = rady + 1; row < H - rady; row++) {
dst[row][col] = dst[(row - 1)][col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
}
for (int row = H - rady; row < H; row++) {
dst[row][col] = (dst[(row - 1)][col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
len --;
}
}
}
delete buffer;
}
template<class T, class A> void boxblur (T** src, A** dst, T* buffer, int radx, int rady, int W, int H)
{
//box blur image; box range = (radx,rady)
float* temp = buffer;
if (radx == 0) {
#ifdef _OPENMP
#pragma omp for
#endif
for (int row = 0; row < H; row++)
for (int col = 0; col < W; col++) {
temp[row * W + col] = (float)src[row][col];
}
} else {
//horizontal blur
#ifdef _OPENMP
#pragma omp for
#endif
for (int row = 0; row < H; row++) {
float len = radx + 1;
float tempval = (float)src[row][0];
for (int j = 1; j <= radx; j++) {
tempval += (float)src[row][j];
}
tempval /= len;
temp[row * W + 0] = tempval;
for (int col = 1; col <= radx; col++) {
temp[row * W + col] = tempval = (tempval * len + (float)src[row][col + radx]) / (len + 1);
len ++;
}
for (int col = radx + 1; col < W - radx; col++) {
temp[row * W + col] = tempval = tempval + ((float)(src[row][col + radx] - src[row][col - radx - 1])) / len;
}
for (int col = W - radx; col < W; col++) {
temp[row * W + col] = tempval = (tempval * len - src[row][col - radx - 1]) / (len - 1);
len --;
}
}
}
if (rady == 0) {
#ifdef _OPENMP
#pragma omp for
#endif
for (int row = 0; row < H; row++)
for (int col = 0; col < W; col++) {
dst[row][col] = temp[row * W + col];
}
} else {
const int numCols = 8; // process numCols columns at once for better usage of L1 cpu cache
#ifdef __SSE2__
vfloat leninitv = F2V( (float)(rady + 1));
vfloat onev = F2V( 1.f );
vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv;
#ifdef _OPENMP
#pragma omp for
#endif
for (int col = 0; col < W - 7; col += 8) {
lenv = leninitv;
tempv = LVFU(temp[0 * W + col]);
temp1v = LVFU(temp[0 * W + col + 4]);
for (int i = 1; i <= rady; i++) {
tempv = tempv + LVFU(temp[i * W + col]);
temp1v = temp1v + LVFU(temp[i * W + col + 4]);
}
tempv = tempv / lenv;
temp1v = temp1v / lenv;
STVFU(dst[0][col], tempv);
STVFU(dst[0][col + 4], temp1v);
for (int row = 1; row <= rady; row++) {
lenp1v = lenv + onev;
tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v;
temp1v = (temp1v * lenv + LVFU(temp[(row + rady) * W + col + 4])) / lenp1v;
STVFU(dst[row][col], tempv);
STVFU(dst[row][col + 4], temp1v);
lenv = lenp1v;
}
rlenv = onev / lenv;
for (int row = rady + 1; row < H - rady; row++) {
tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ;
temp1v = temp1v + (LVFU(temp[(row + rady) * W + col + 4]) - LVFU(temp[(row - rady - 1) * W + col + 4])) * rlenv ;
STVFU(dst[row][col], tempv);
STVFU(dst[row][col + 4], temp1v);
}
for (int row = H - rady; row < H; row++) {
lenm1v = lenv - onev;
tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v;
temp1v = (temp1v * lenv - LVFU(temp[(row - rady - 1) * W + col + 4])) / lenm1v;
STVFU(dst[row][col], tempv);
STVFU(dst[row][col + 4], temp1v);
lenv = lenm1v;
}
}
#else
//vertical blur
#ifdef _OPENMP
#pragma omp for
#endif
for (int col = 0; col < W - numCols + 1; col += 8) {
float len = rady + 1;
for(int k = 0; k < numCols; k++) {
dst[0][col + k] = temp[0 * W + col + k];
}
for (int i = 1; i <= rady; i++) {
for(int k = 0; k < numCols; k++) {
dst[0][col + k] += temp[i * W + col + k];
}
}
for(int k = 0; k < numCols; k++) {
dst[0][col + k] /= len;
}
for (int row = 1; row <= rady; row++) {
for(int k = 0; k < numCols; k++) {
dst[row][col + k] = (dst[(row - 1)][col + k] * len + temp[(row + rady) * W + col + k]) / (len + 1);
}
len ++;
}
for (int row = rady + 1; row < H - rady; row++) {
for(int k = 0; k < numCols; k++) {
dst[row][col + k] = dst[(row - 1)][col + k] + (temp[(row + rady) * W + col + k] - temp[(row - rady - 1) * W + col + k]) / len;
}
}
for (int row = H - rady; row < H; row++) {
for(int k = 0; k < numCols; k++) {
dst[row][col + k] = (dst[(row - 1)][col + k] * len - temp[(row - rady - 1) * W + col + k]) / (len - 1);
}
len --;
}
}
#endif
#ifdef _OPENMP
#pragma omp single
#endif
for (int col = W - (W % numCols); col < W; col++) {
float len = rady + 1;
dst[0][col] = temp[0 * W + col] / len;
for (int i = 1; i <= rady; i++) {
dst[0][col] += temp[i * W + col] / len;
}
for (int row = 1; row <= rady; row++) {
dst[row][col] = (dst[(row - 1)][col] * len + temp[(row + rady) * W + col]) / (len + 1);
len ++;
}
for (int row = rady + 1; row < H - rady; row++) {
dst[row][col] = dst[(row - 1)][col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
}
for (int row = H - rady; row < H; row++) {
dst[row][col] = (dst[(row - 1)][col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
len --;
}
}
}
}
inline void boxblur (float** src, float** dst, int radius, int W, int H, bool multiThread)
{
//box blur using rowbuffers and linebuffers instead of a full size buffer
if (radius == 0) {
if (src != dst) {
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
for (int row = 0; row < H; row++) {
for (int col = 0; col < W; col++) {
dst[row][col] = src[row][col];
}
}
}
return;
}
constexpr int numCols = 8; // process numCols columns at once for better usage of L1 cpu cache
#ifdef _OPENMP
#pragma omp parallel if (multiThread)
#endif
{
std::unique_ptr<float[]> buffer(new float[numCols * (radius + 1)]);
//horizontal blur
float* const lineBuffer = buffer.get();
// float* const lineBuffer = buffer;
#ifdef _OPENMP
#pragma omp for
#endif
for (int row = 0; row < H; row++) {
float len = radius + 1;
float tempval = src[row][0];
lineBuffer[0] = tempval;
for (int j = 1; j <= radius; j++) {
tempval += src[row][j];
}
tempval /= len;
dst[row][0] = tempval;
for (int col = 1; col <= radius; col++) {
lineBuffer[col] = src[row][col];
tempval = (tempval * len + src[row][col + radius]) / (len + 1);
dst[row][col] = tempval;
++len;
}
int pos = 0;
for (int col = radius + 1; col < W - radius; col++) {
const float oldVal = lineBuffer[pos];
lineBuffer[pos] = src[row][col];
dst[row][col] = tempval = tempval + (src[row][col + radius] - oldVal) / len;
++pos;
pos = pos <= radius ? pos : 0;
}
for (int col = W - radius; col < W; col++) {
dst[row][col] = tempval = (tempval * len - lineBuffer[pos]) / (len - 1);
--len;
++pos;
pos = pos <= radius ? pos : 0;
}
}
//vertical blur
#ifdef __SSE2__
vfloat (* const rowBuffer)[2] = (vfloat(*)[2]) buffer.get();
const vfloat leninitv = F2V(radius + 1);
const vfloat onev = F2V(1.f);
vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv;
#ifdef _OPENMP
#pragma omp for nowait
#endif
for (int col = 0; col < W - 7; col += 8) {
lenv = leninitv;
tempv = LVFU(dst[0][col]);
temp1v = LVFU(dst[0][col + 4]);
rowBuffer[0][0] = tempv;
rowBuffer[0][1] = temp1v;
for (int i = 1; i <= radius; i++) {
tempv = tempv + LVFU(dst[i][col]);
temp1v = temp1v + LVFU(dst[i][col + 4]);
}
tempv = tempv / lenv;
temp1v = temp1v / lenv;
STVFU(dst[0][col], tempv);
STVFU(dst[0][col + 4], temp1v);
for (int row = 1; row <= radius; row++) {
rowBuffer[row][0] = LVFU(dst[row][col]);
rowBuffer[row][1] = LVFU(dst[row][col + 4]);
lenp1v = lenv + onev;
tempv = (tempv * lenv + LVFU(dst[row + radius][col])) / lenp1v;
temp1v = (temp1v * lenv + LVFU(dst[row + radius][col + 4])) / lenp1v;
STVFU(dst[row][col], tempv);
STVFU(dst[row][col + 4], temp1v);
lenv = lenp1v;
}
rlenv = onev / lenv;
int pos = 0;
for (int row = radius + 1; row < H - radius; row++) {
vfloat oldVal0 = rowBuffer[pos][0];
vfloat oldVal1 = rowBuffer[pos][1];
rowBuffer[pos][0] = LVFU(dst[row][col]);
rowBuffer[pos][1] = LVFU(dst[row][col + 4]);
tempv = tempv + (LVFU(dst[row + radius][col]) - oldVal0) * rlenv ;
temp1v = temp1v + (LVFU(dst[row + radius][col + 4]) - oldVal1) * rlenv ;
STVFU(dst[row][col], tempv);
STVFU(dst[row][col + 4], temp1v);
++pos;
pos = pos <= radius ? pos : 0;
}
for (int row = H - radius; row < H; row++) {
lenm1v = lenv - onev;
tempv = (tempv * lenv - rowBuffer[pos][0]) / lenm1v;
temp1v = (temp1v * lenv - rowBuffer[pos][1]) / lenm1v;
STVFU(dst[row][col], tempv);
STVFU(dst[row][col + 4], temp1v);
lenv = lenm1v;
++pos;
pos = pos <= radius ? pos : 0;
}
}
#else
float (* const rowBuffer)[8] = (float(*)[8]) buffer.get();
#ifdef _OPENMP
#pragma omp for nowait
#endif
for (int col = 0; col < W - numCols + 1; col += 8) {
float len = radius + 1;
for (int k = 0; k < numCols; k++) {
rowBuffer[0][k] = dst[0][col + k];
}
for (int i = 1; i <= radius; i++) {
for (int k = 0; k < numCols; k++) {
dst[0][col + k] += dst[i][col + k];
}
}
for(int k = 0; k < numCols; k++) {
dst[0][col + k] /= len;
}
for (int row = 1; row <= radius; row++) {
for(int k = 0; k < numCols; k++) {
rowBuffer[row][k] = dst[row][col + k];
dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1);
}
len ++;
}
int pos = 0;
for (int row = radius + 1; row < H - radius; row++) {
for(int k = 0; k < numCols; k++) {
float oldVal = rowBuffer[pos][k];
rowBuffer[pos][k] = dst[row][col + k];
dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) / len;
}
++pos;
pos = pos <= radius ? pos : 0;
}
for (int row = H - radius; row < H; row++) {
for(int k = 0; k < numCols; k++) {
dst[row][col + k] = (dst[row - 1][col + k] * len - rowBuffer[pos][k]) / (len - 1);
}
len --;
++pos;
pos = pos <= radius ? pos : 0;
}
}
#endif
//vertical blur, remaining columns
#ifdef _OPENMP
#pragma omp single
#endif
{
const int remaining = W % numCols;
if (remaining > 0) {
float (* const rowBuffer)[8] = (float(*)[8]) buffer.get();
const int col = W - remaining;
float len = radius + 1;
for(int k = 0; k < remaining; ++k) {
rowBuffer[0][k] = dst[0][col + k];
}
for (int row = 1; row <= radius; ++row) {
for(int k = 0; k < remaining; ++k) {
dst[0][col + k] += dst[row][col + k];
}
}
for(int k = 0; k < remaining; ++k) {
dst[0][col + k] /= len;
}
for (int row = 1; row <= radius; ++row) {
for(int k = 0; k < remaining; ++k) {
rowBuffer[row][k] = dst[row][col + k];
dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1);
}
len ++;
}
const float rlen = 1.f / len;
int pos = 0;
for (int row = radius + 1; row < H - radius; ++row) {
for(int k = 0; k < remaining; ++k) {
float oldVal = rowBuffer[pos][k];
rowBuffer[pos][k] = dst[row][col + k];
dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) * rlen;
}
++pos;
pos = pos <= radius ? pos : 0;
}
for (int row = H - radius; row < H; ++row) {
for(int k = 0; k < remaining; ++k) {
dst[row][col + k] = (dst[(row - 1)][col + k] * len - rowBuffer[pos][k]) / (len - 1);
}
len --;
++pos;
pos = pos <= radius ? pos : 0;
}
}
}
}
}
template<class T, class A> void boxblur (T* src, A* dst, A* buffer, int radx, int rady, int W, int H)
{
//box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1)
float* temp = buffer;
if (radx == 0) {
for (int row = 0; row < H; row++)
for (int col = 0; col < W; col++) {
temp[row * W + col] = src[row * W + col];
}
} else {
//horizontal blur
for (int row = H - 1; row >= 0; row--) {
int len = radx + 1;
float tempval = (float)src[row * W];
for (int j = 1; j <= radx; j++) {
tempval += (float)src[row * W + j];
}
tempval = tempval / len;
temp[row * W] = tempval;
for (int col = 1; col <= radx; col++) {
tempval = (tempval * len + src[row * W + col + radx]) / (len + 1);
temp[row * W + col] = tempval;
len ++;
}
float reclen = 1.f / len;
for (int col = radx + 1; col < W - radx; col++) {
tempval = tempval + ((float)(src[row * W + col + radx] - src[row * W + col - radx - 1])) * reclen;
temp[row * W + col] = tempval;
}
for (int col = W - radx; col < W; col++) {
tempval = (tempval * len - src[row * W + col - radx - 1]) / (len - 1);
temp[row * W + col] = tempval;
len --;
}
}
}
if (rady == 0) {
for (int row = 0; row < H; row++)
for (int col = 0; col < W; col++) {
dst[row * W + col] = temp[row * W + col];
}
} else {
//vertical blur
#ifdef __SSE2__
vfloat leninitv = F2V( (float)(rady + 1));
vfloat onev = F2V( 1.f );
vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv;
int col;
for (col = 0; col < W - 7; col += 8) {
lenv = leninitv;
tempv = LVFU(temp[0 * W + col]);
temp1v = LVFU(temp[0 * W + col + 4]);
for (int i = 1; i <= rady; i++) {
tempv = tempv + LVFU(temp[i * W + col]);
temp1v = temp1v + LVFU(temp[i * W + col + 4]);
}
tempv = tempv / lenv;
temp1v = temp1v / lenv;
STVFU(dst[0 * W + col], tempv);
STVFU(dst[0 * W + col + 4], temp1v);
for (int row = 1; row <= rady; row++) {
lenp1v = lenv + onev;
tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v;
temp1v = (temp1v * lenv + LVFU(temp[(row + rady) * W + col + 4])) / lenp1v;
STVFU(dst[row * W + col], tempv);
STVFU(dst[row * W + col + 4], temp1v);
lenv = lenp1v;
}
rlenv = onev / lenv;
for (int row = rady + 1; row < H - rady; row++) {
tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ;
temp1v = temp1v + (LVFU(temp[(row + rady) * W + col + 4]) - LVFU(temp[(row - rady - 1) * W + col + 4])) * rlenv ;
STVFU(dst[row * W + col], tempv);
STVFU(dst[row * W + col + 4], temp1v);
}
for (int row = H - rady; row < H; row++) {
lenm1v = lenv - onev;
tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v;
temp1v = (temp1v * lenv - LVFU(temp[(row - rady - 1) * W + col + 4])) / lenm1v;
STVFU(dst[row * W + col], tempv);
STVFU(dst[row * W + col + 4], temp1v);
lenv = lenm1v;
}
}
for (; col < W - 3; col += 4) {
lenv = leninitv;
tempv = LVFU(temp[0 * W + col]);
for (int i = 1; i <= rady; i++) {
tempv = tempv + LVFU(temp[i * W + col]);
}
tempv = tempv / lenv;
STVFU(dst[0 * W + col], tempv);
for (int row = 1; row <= rady; row++) {
lenp1v = lenv + onev;
tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v;
STVFU(dst[row * W + col], tempv);
lenv = lenp1v;
}
rlenv = onev / lenv;
for (int row = rady + 1; row < H - rady; row++) {
tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ;
STVFU(dst[row * W + col], tempv);
}
for (int row = H - rady; row < H; row++) {
lenm1v = lenv - onev;
tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v;
STVFU(dst[row * W + col], tempv);
lenv = lenm1v;
}
}
for (; col < W; col++) {
int len = rady + 1;
dst[0 * W + col] = temp[0 * W + col] / len;
for (int i = 1; i <= rady; i++) {
dst[0 * W + col] += temp[i * W + col] / len;
}
for (int row = 1; row <= rady; row++) {
dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1);
len ++;
}
for (int row = rady + 1; row < H - rady; row++) {
dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
}
for (int row = H - rady; row < H; row++) {
dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
len --;
}
}
#else
for (int col = 0; col < W; col++) {
int len = rady + 1;
dst[0 * W + col] = temp[0 * W + col] / len;
for (int i = 1; i <= rady; i++) {
dst[0 * W + col] += temp[i * W + col] / len;
}
for (int row = 1; row <= rady; row++) {
dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1);
len ++;
}
for (int row = rady + 1; row < H - rady; row++) {
dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
}
for (int row = H - rady; row < H; row++) {
dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
len --;
}
}
#endif
}
}
template<class T, class A> void boxabsblur (T* src, A* dst, int radx, int rady, int W, int H, float * temp)
{
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1)
if (radx == 0) {
for (int row = 0; row < H; row++)
for (int col = 0; col < W; col++) {
temp[row * W + col] = fabs(src[row * W + col]);
}
} else {
//horizontal blur
for (int row = 0; row < H; row++) {
int len = radx + 1;
float tempval = fabsf((float)src[row * W + 0]);
for (int j = 1; j <= radx; j++) {
tempval += fabsf((float)src[row * W + j]);
}
tempval /= len;
temp[row * W + 0] = tempval;
for (int col = 1; col <= radx; col++) {
tempval = (tempval * len + fabsf(src[row * W + col + radx])) / (len + 1);
temp[row * W + col] = tempval;
len ++;
}
float rlen = 1.f / (float)len;
for (int col = radx + 1; col < W - radx; col++) {
tempval = tempval + ((float)(fabsf(src[row * W + col + radx]) - fabsf(src[row * W + col - radx - 1]))) * rlen;
temp[row * W + col] = tempval;
}
for (int col = W - radx; col < W; col++) {
tempval = (tempval * len - fabsf(src[row * W + col - radx - 1])) / (len - 1);
temp[row * W + col] = tempval;
len --;
}
}
}
if (rady == 0) {
for (int row = 0; row < H; row++)
for (int col = 0; col < W; col++) {
dst[row * W + col] = temp[row * W + col];
}
} else {
//vertical blur
#ifdef __SSE2__
vfloat leninitv = F2V( (float)(rady + 1));
vfloat onev = F2V( 1.f );
vfloat tempv, lenv, lenp1v, lenm1v, rlenv;
for (int col = 0; col < W - 3; col += 4) {
lenv = leninitv;
tempv = LVF(temp[0 * W + col]);
for (int i = 1; i <= rady; i++) {
tempv = tempv + LVF(temp[i * W + col]);
}
tempv = tempv / lenv;
STVF(dst[0 * W + col], tempv);
for (int row = 1; row <= rady; row++) {
lenp1v = lenv + onev;
tempv = (tempv * lenv + LVF(temp[(row + rady) * W + col])) / lenp1v;
STVF(dst[row * W + col], tempv);
lenv = lenp1v;
}
rlenv = onev / lenv;
for (int row = rady + 1; row < H - rady; row++) {
tempv = tempv + (LVF(temp[(row + rady) * W + col]) - LVF(temp[(row - rady - 1) * W + col])) * rlenv;
STVF(dst[row * W + col], tempv);
}
for (int row = H - rady; row < H; row++) {
lenm1v = lenv - onev;
tempv = (tempv * lenv - LVF(temp[(row - rady - 1) * W + col])) / lenm1v;
STVF(dst[row * W + col], tempv);
lenv = lenm1v;
}
}
for (int col = W - (W % 4); col < W; col++) {
int len = rady + 1;
dst[0 * W + col] = temp[0 * W + col] / len;
for (int i = 1; i <= rady; i++) {
dst[0 * W + col] += temp[i * W + col] / len;
}
for (int row = 1; row <= rady; row++) {
dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1);
len ++;
}
for (int row = rady + 1; row < H - rady; row++) {
dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
}
for (int row = H - rady; row < H; row++) {
dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
len --;
}
}
#else
for (int col = 0; col < W; col++) {
int len = rady + 1;
dst[0 * W + col] = temp[0 * W + col] / len;
for (int i = 1; i <= rady; i++) {
dst[0 * W + col] += temp[i * W + col] / len;
}
for (int row = 1; row <= rady; row++) {
dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1);
len ++;
}
for (int row = rady + 1; row < H - rady; row++) {
dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
}
for (int row = H - rady; row < H; row++) {
dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
len --;
}
}
#endif
}
}
}
#endif /* _BOXBLUR_H_ */

View File

@ -372,7 +372,7 @@ public:
void DeNoise(int call, float * slidL, float * slida, float * slidb, int aut, bool noiscfactiv, const struct local_params& lp, LabImage* originalmaskbl, LabImage * bufmaskblurbl, int levred, float huerefblur, float lumarefblur, float chromarefblur, LabImage* original, LabImage* transformed, int cx, int cy, int sk, const LocwavCurve& locwavCurvehue, bool locwavhueutili);
void fftw_denoise(int GW, int GH, int max_numblox_W, int min_numblox_W, float **tmp1, array2D<float> *Lin, int numThreads, const struct local_params & lp, int chrom);
void fftw_denoise(int sk, int GW, int GH, int max_numblox_W, int min_numblox_W, float **tmp1, array2D<float> *Lin, int numThreads, const struct local_params & lp, int chrom);
void ColorLight_Local(float moddE, float powdE, int call, LabImage * bufcolorig, LabImage * originalmask, float **buflight, float **bufchro, float **bufchroslid, float ** bufhh, float ** buflightslid, bool &LHutili, bool &HHutili, const float hueplus, const float huemoins, const float hueref, const float dhue, const float chromaref, const float lumaref, float sobelref, float ** blend2, LUTf & lllocalcurve, const LocLHCurve & loclhCurve, const LocHHCurve & lochhCurve, LUTf & lightCurveloc, const local_params& lp, LabImage* original, LabImage* transformed, int cx, int cy, int sk);
void InverseColorLight_Local(bool tonequ, bool tonecurv, int sp, int senstype, struct local_params& lp, LabImage * originalmask, const LUTf& lightCurveloc, const LUTf& hltonecurveloc, const LUTf& shtonecurveloc, const LUTf& tonecurveloc, const LUTf& exlocalcurve, const LUTf& cclocalcurve, float adjustr, bool localcutili, const LUTf& lllocalcurve, bool locallutili, LabImage* original, LabImage* transformed, int cx, int cy, const float hueref, const float chromaref, const float lumaref, int sk);

View File

@ -49,6 +49,7 @@
#define BENCHMARK
#include "StopWatch.h"
#include "guidedfilter.h"
#include "boxblural.h"
#pragma GCC diagnostic warning "-Wall"
@ -250,6 +251,8 @@ float calcreducdE(float dE, float maxdE, float mindE, float maxdElim, float mind
}
}
void deltaEforLaplace(float *dE, const float lap, int bfw, int bfh, rtengine::LabImage* bufexporig, const float hueref, const float chromaref, const float lumaref)
{
@ -659,7 +662,7 @@ struct local_params {
bool activspot;
float thrlow;
float thrhigh;
// bool usemask;
bool usemask;
float lnoiselow;
};
@ -780,7 +783,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall
lp.thrlow = locallab.spots.at(sp).levelthrlow;
lp.thrhigh = locallab.spots.at(sp).levelthr;
// lp.usemask = locallab.spots.at(sp).usemask;
lp.usemask = locallab.spots.at(sp).usemask;
lp.lnoiselow = locallab.spots.at(sp).lnoiselow;
// printf("llColorMask=%i lllcMask=%i llExpMask=%i llSHMask=%i llcbMask=%i llretiMask=%i lltmMask=%i llblMask=%i llvibMask=%i\n", llColorMask, lllcMask, llExpMask, llSHMask, llcbMask, llretiMask, lltmMask, llblMask, llvibMask);
@ -3886,6 +3889,48 @@ static void showmask(int lumask, const local_params& lp, int xstart, int ystart,
}
}
}
//from A.Griggio...very similar to discrete_laplacian_threhold...some differences with ceiling and data format
void laplacian(const array2D<float> &src, array2D<float> &dst, int bfw, int bfh, float threshold, float ceiling, float factor, bool multiThread)
{
const int W = bfw;
const int H = bfh;
const auto X =
[W](int x) -> int
{
return x < 0 ? x+2 : (x >= W ? x-2 : x);
};
const auto Y =
[H](int y) -> int
{
return y < 0 ? y+2 : (y >= H ? y-2 : y);
};
const auto get =
[&src](int y, int x) -> float
{
return std::max(src[y][x], 0.f);
};
dst(W, H);
const float f = factor / ceiling;
#ifdef _OPENMP
# pragma omp parallel for if (multiThread)
#endif
for (int y = 0; y < H; ++y) {
int n = Y(y-1), s = Y(y+1);
for (int x = 0; x < W; ++x) {
int w = X(x-1), e = X(x+1);
float v = -8.f * get(y, x) + get(n, x) + get(s, x) + get(y, w) + get(y, e) + get(n, w) + get(n, e) + get(s, w) + get(s, e);
dst[y][x] = LIM(std::abs(v) - threshold, 0.f, ceiling) * f;
}
}
}
void ImProcFunctions::discrete_laplacian_threshold(float * data_out, const float * data_in, size_t nx, size_t ny, float t)
{
@ -8412,7 +8457,7 @@ void ImProcFunctions::wavcontrast4(struct local_params& lp, float ** tmp, float
}
void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_numblox_W, float **tmp1, array2D<float> *Lin, int numThreads, const struct local_params & lp, int chrom)
void ImProcFunctions::fftw_denoise(int sk, int GW, int GH, int max_numblox_W, int min_numblox_W, float **tmp1, array2D<float> *Lin, int numThreads, const struct local_params & lp, int chrom)
{
// BENCHFUN
@ -8596,30 +8641,51 @@ void ImProcFunctions::fftw_denoise(int GW, int GH, int max_numblox_W, int min_nu
}//end of vertical block loop
}
//Threshold DCT from Alberto Grigio
//Threshold DCT from Alberto Grigio, adapted to Rawtherapee
const int detail_thresh = lp.detailthr;
array2D<float> mask;
if (detail_thresh > 0) {
mask(GW, GH);
float thr = log2lin(float(detail_thresh) / 200.f, 100.f);
buildBlendMask(prov, mask, GW, GH, thr);
if (lp.usemask) {//with Laplacian
float amount = LIM01(float(detail_thresh)/100.f);
float thr = (1.f - amount);
float alph = params_Ldetail / 100.f;
array2D<float> LL(GW, GH, prov, ARRAY2D_BYREFERENCE);
laplacian(LL, mask, GW, GH, 25.f, 20000.f, amount, false);
for (int i = 0; i < GH; ++i) {
for (int j = 0; j < GW; ++j) {
mask[i][j] = LIM01(mask[i][j]+ thr);
}
}
for (int i = 0; i < 3; ++i) {
boxblur(mask, mask, 10 / sk, GW, GH, false);
}
for (int i = 0; i < GH; ++i) {
for (int j = 0; j < GW; ++j) {
float k = 1.f - mask[i][j] * alph;
mask[i][j] = 1.f - (k * k);
}
}
} else {//with blend mask
float thr = log2lin(float(detail_thresh) / 200.f, 100.f);
buildBlendMask(prov, mask, GW, GH, thr);
#ifdef _OPENMP
#pragma omp parallel if (multiThread)
#endif
{
gaussianBlur(mask, mask, GW, GH, 20.0);
}
array2D<float> m2(GW, GH);
constexpr float alfa = 0.856f;
const float beta = 1.f + std::sqrt(log2lin(thr, 100.f));
buildGradientsMask(GW, GH, prov, m2, params_Ldetail / 100.f, 7, 3, alfa, beta, multiThread);
for (int i = 0; i < GH; ++i) {
for (int j = 0; j < GW; ++j) {
mask[i][j] *= m2[i][j];
{
gaussianBlur(mask, mask, GW, GH, 20.0 / sk);
}
}
array2D<float> m2(GW, GH);
constexpr float alfa = 0.856f;
const float beta = 1.f + std::sqrt(log2lin(thr, 100.f));
buildGradientsMask(GW, GH, prov, m2, params_Ldetail / 100.f, 7, 3, alfa, beta, multiThread);
for (int i = 0; i < GH; ++i) {
for (int j = 0; j < GW; ++j) {
mask[i][j] *= m2[i][j];
}
}
}
}
@ -9233,7 +9299,7 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
if (!Ldecomp.memory_allocation_failed() && aut == 0) {
if ((lp.noiself >= 0.01f || lp.noiself0 >= 0.01f || lp.noiself2 >= 0.01f || lp.noiselc >= 0.01f) && levred == 7 && lp.noiseldetail != 100.f) {
fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.L, Lin, numThreads, lp, 0);
fftw_denoise(sk, GW, GH, max_numblox_W, min_numblox_W, tmp1.L, Lin, numThreads, lp, 0);
}
}
@ -9254,7 +9320,7 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
if (!adecomp.memory_allocation_failed() && aut == 0) {
if ((lp.noisecf >= 0.01f || lp.noisecc >= 0.01f) && levred == 7 && lp.noisechrodetail != 100.f) {
fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.a, Ain, numThreads, lp, 1);
fftw_denoise(sk, GW, GH, max_numblox_W, min_numblox_W, tmp1.a, Ain, numThreads, lp, 1);
}
}
@ -9277,7 +9343,7 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
if (!bdecomp.memory_allocation_failed() && aut == 0) {
if ((lp.noisecf >= 0.01f || lp.noisecc >= 0.01f) && levred == 7 && lp.noisechrodetail != 100.f) {
fftw_denoise(GW, GH, max_numblox_W, min_numblox_W, tmp1.b, Bin, numThreads, lp, 1);
fftw_denoise(sk, GW, GH, max_numblox_W, min_numblox_W, tmp1.b, Bin, numThreads, lp, 1);
}
}
@ -9835,7 +9901,7 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
if ((lp.noiself >= 0.01f || lp.noiself0 >= 0.01f || lp.noiself2 >= 0.01f || lp.noiselc >= 0.01f) && levred == 7 && lp.noiseldetail != 100.f) {
fftw_denoise(bfw, bfh, max_numblox_W, min_numblox_W, bufwv.L, Lin, numThreads, lp, 0);
fftw_denoise(sk, bfw, bfh, max_numblox_W, min_numblox_W, bufwv.L, Lin, numThreads, lp, 0);
}
}
@ -9856,7 +9922,7 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
if (!adecomp.memory_allocation_failed() && aut == 0) {
if ((lp.noisecf >= 0.001f || lp.noisecc >= 0.001f) && levred == 7 && lp.noisechrodetail != 100.f) {
fftw_denoise(bfw, bfh, max_numblox_W, min_numblox_W, bufwv.a, Ain, numThreads, lp, 1);
fftw_denoise(sk, bfw, bfh, max_numblox_W, min_numblox_W, bufwv.a, Ain, numThreads, lp, 1);
}
}
@ -9877,7 +9943,7 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl
if (!bdecomp.memory_allocation_failed() && aut == 0) {
if ((lp.noisecf >= 0.001f || lp.noisecc >= 0.001f) && levred == 7 && lp.noisechrodetail != 100.f) {
fftw_denoise(bfw, bfh, max_numblox_W, min_numblox_W, bufwv.b, Bin, numThreads, lp, 1);
fftw_denoise(sk, bfw, bfh, max_numblox_W, min_numblox_W, bufwv.b, Bin, numThreads, lp, 1);
}
}

View File

@ -1007,8 +1007,8 @@ enum ProcEventCode {
EvlocallabwavCurvehue = 981,
Evlocallablevelthr = 982,
Evlocallablevelthrlow = 983,
// Evlocallabusemask1 = 984,
Evlocallablnoiselow = 984,
Evlocallabusemask1 = 984,
Evlocallablnoiselow = 985,
NUMOFEVENTS
};

View File

@ -3307,7 +3307,7 @@ LocallabParams::LocallabSpot::LocallabSpot() :
quamethod("cons"),
blurMethod("norm"),
medMethod("33"),
// usemask(false),
usemask(false),
levelthr(40.),
lnoiselow(1.),
levelthrlow(12.),
@ -4350,7 +4350,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const
&& chroMethod == other.chroMethod
&& quamethod == other.quamethod
&& blurMethod == other.blurMethod
// && usemask == other.usemask
&& usemask == other.usemask
&& levelthr == other.levelthr
&& lnoiselow == other.lnoiselow
&& levelthrlow == other.levelthrlow
@ -5936,7 +5936,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || spot_edited->chroMethod, "Locallab", "ChroMethod_" + index_str, spot.chroMethod, keyFile);
saveToKeyfile(!pedited || spot_edited->quamethod, "Locallab", "QuaMethod_" + index_str, spot.quamethod, keyFile);
saveToKeyfile(!pedited || spot_edited->blurMethod, "Locallab", "BlurMethod_" + index_str, spot.blurMethod, keyFile);
// saveToKeyfile(!pedited || spot_edited->usemask, "Locallab", "Usemaskb_" + index_str, spot.usemask, keyFile);
saveToKeyfile(!pedited || spot_edited->usemask, "Locallab", "Usemaskb_" + index_str, spot.usemask, keyFile);
saveToKeyfile(!pedited || spot_edited->levelthr, "Locallab", "Levelthr_" + index_str, spot.levelthr, keyFile);
saveToKeyfile(!pedited || spot_edited->lnoiselow, "Locallab", "Lnoiselow_" + index_str, spot.lnoiselow, keyFile);
saveToKeyfile(!pedited || spot_edited->levelthrlow, "Locallab", "Levelthrlow_" + index_str, spot.levelthrlow, keyFile);
@ -7738,7 +7738,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "ChroMethod_" + index_str, pedited, spot.chroMethod, spotEdited.chroMethod);
assignFromKeyfile(keyFile, "Locallab", "QuaMethod_" + index_str, pedited, spot.quamethod, spotEdited.quamethod);
assignFromKeyfile(keyFile, "Locallab", "BlurMethod_" + index_str, pedited, spot.blurMethod, spotEdited.blurMethod);
// assignFromKeyfile(keyFile, "Locallab", "Usemaskb_" + index_str, pedited, spot.usemask, spotEdited.usemask);
assignFromKeyfile(keyFile, "Locallab", "Usemaskb_" + index_str, pedited, spot.usemask, spotEdited.usemask);
assignFromKeyfile(keyFile, "Locallab", "Levelthr_" + index_str, pedited, spot.levelthr, spotEdited.levelthr);
assignFromKeyfile(keyFile, "Locallab", "Lnoiselow_" + index_str, pedited, spot.lnoiselow, spotEdited.lnoiselow);
assignFromKeyfile(keyFile, "Locallab", "Levelthrlow_" + index_str, pedited, spot.levelthrlow, spotEdited.levelthrlow);

View File

@ -1214,7 +1214,7 @@ struct LocallabParams {
Glib::ustring quamethod; // cons agre
Glib::ustring blurMethod; // norm, inv
Glib::ustring medMethod; // none, 33, 55, 77, 99
// bool usemask;
bool usemask;
double levelthr;
double lnoiselow;
double levelthrlow;

View File

@ -1011,7 +1011,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, //EvlocallabwavCurvehue
LUMINANCECURVE, // Evlocallablevelthr
LUMINANCECURVE, // Evlocallablevelthrlow
// LUMINANCECURVE, //Evlocallabusemask1
LUMINANCECURVE, //Evlocallabusemask1
LUMINANCECURVE // Evlocallablnoiselow
};

View File

@ -5763,7 +5763,7 @@ LocallabBlur::LocallabBlur():
expdenoise1(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI1_EXP")))),
maskusable(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_MASKUSABLE")))),
maskunusable(Gtk::manage(new Gtk::Label(M("TP_LOCALLAB_MASKUNUSABLE")))),
// usemask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_USEMASK")))),
usemask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_USEMASK")))),
lnoiselow(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MASKLNOISELOW"), 0.7, 2., 0.01, 1.))),
levelthr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MASKLCTHR"), 10., 100., 1., 40.))),
levelthrlow(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MASKLCTHRLOW"), 1., 100., 1., 12.))),
@ -5778,6 +5778,7 @@ LocallabBlur::LocallabBlur():
noisechrof(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROFINE"), MINCHRO, MAXCHRO, 0.01, 0.))),
noisechroc(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHROCOARSE"), MINCHRO, MAXCHROCC, 0.01, 0.))),
noisechrodetail(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISECHRODETAIL"), 0., 100., 0.01, 50.))),
detailFrame(Gtk::manage(new Gtk::Frame(M("TP_LOCALLAB_DETAILFRA")))),
detailthr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_DETAILTHR"), 0, 100, 1, 50))),
adjblur(Gtk::manage(new Adjuster(M("TP_LOCALLAB_ADJ"), -100., 100., 1., 0., Gtk::manage(new RTImage("circle-blue-yellow-small.png")), Gtk::manage(new RTImage("circle-red-green-small.png"))))),
bilateral(Gtk::manage(new Adjuster(M("TP_LOCALLAB_BILATERAL"), 0, 100, 1, 0))),
@ -5829,7 +5830,7 @@ LocallabBlur::LocallabBlur():
blMethodConn = blMethod->signal_changed().connect(sigc::mem_fun(*this, &LocallabBlur::blMethodChanged));
fftwblConn = fftwbl->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::fftwblChanged));
// usemaskConn = usemask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::usemaskChanged));
usemaskConn = usemask->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::usemaskChanged));
invblConn = invbl->signal_toggled().connect(sigc::mem_fun(*this, &LocallabBlur::invblChanged));
radius->setAdjusterListener(this);
@ -5931,6 +5932,7 @@ LocallabBlur::LocallabBlur():
noisechrodetail->setAdjusterListener(this);
detailFrame->set_label_align(0.025, 0.5);
detailthr->setAdjusterListener(this);
adjblur->setAdjusterListener(this);
@ -6057,7 +6059,6 @@ LocallabBlur::LocallabBlur():
wavBox->pack_start(*noiselequal);
wavBox->pack_start(*LocalcurveEditorwavhue, Gtk::PACK_SHRINK, 4);
ToolParamBlock* const wavBox1 = Gtk::manage(new ToolParamBlock());
// wavBox1->pack_start(*usemask, Gtk::PACK_SHRINK, 0);
wavBox1->pack_start(*maskusable, Gtk::PACK_SHRINK, 0);
wavBox1->pack_start(*maskunusable, Gtk::PACK_SHRINK, 0);
wavBox1->pack_start(*lnoiselow, Gtk::PACK_SHRINK, 0);
@ -6068,8 +6069,12 @@ LocallabBlur::LocallabBlur():
wavBox->pack_start(*noisechrof);
wavBox->pack_start(*noisechroc);
wavBox->pack_start(*noisechrodetail);
wavBox->pack_start(*detailthr);
wavBox->pack_start(*adjblur);
ToolParamBlock* const detailBox = Gtk::manage(new ToolParamBlock());
detailBox->pack_start(*detailthr);
detailBox->pack_start(*usemask, Gtk::PACK_SHRINK, 0);
detailFrame->add(*detailBox);
wavBox->pack_start(*detailFrame);
wavFrame->add(*wavBox);
denoisebox->pack_start(*wavFrame);
denoisebox->pack_start(*bilateral);
@ -6260,6 +6265,7 @@ void LocallabBlur::neutral_pressed ()
quamethod->set_active (0);
wavshapeden->setCurve(defSpot.locwavcurveden);
wavhue->setCurve(defSpot.locwavcurvehue);
usemask->set_active(defSpot.usemask);
}
void LocallabBlur::setDefaultExpanderVisibility()
@ -6276,7 +6282,7 @@ void LocallabBlur::disableListener()
blMethodConn.block(true);
fftwblConn.block(true);
// usemaskConn.block(true);
usemaskConn.block(true);
invblConn.block(true);
medMethodConn.block(true);
blurMethodConn.block(true);
@ -6295,7 +6301,7 @@ void LocallabBlur::enableListener()
blMethodConn.block(false);
fftwblConn.block(false);
// usemaskConn.block(false);
usemaskConn.block(false);
invblConn.block(false);
medMethodConn.block(false);
blurMethodConn.block(false);
@ -6334,7 +6340,7 @@ void LocallabBlur::read(const rtengine::procparams::ProcParams* pp, const Params
}
fftwbl->set_active(spot.fftwbl);
// usemask->set_active(spot.usemask);
usemask->set_active(spot.usemask);
invbl->set_active(spot.invbl);
radius->setValue(spot.radius);
strength->setValue(spot.strength);
@ -6459,7 +6465,7 @@ void LocallabBlur::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped
}
spot.fftwbl = fftwbl->get_active();
// spot.usemask = usemask->get_active();
spot.usemask = usemask->get_active();
spot.invbl = invbl->get_active();
spot.radius = radius->getValue();
spot.strength = strength->getIntValue();
@ -6994,7 +7000,7 @@ void LocallabBlur::convertParamToSimple()
levelthr->setValue(defSpot.levelthr);
lnoiselow->setValue(defSpot.lnoiselow);
levelthrlow->setValue(defSpot.levelthrlow);
// usemask->set_active(defSpot.usemask);
usemask->set_active(defSpot.usemask);
// Enable all listeners
enableListener();
@ -7130,7 +7136,7 @@ void LocallabBlur::fftwblChanged()
}
}
}
/*
void LocallabBlur::usemaskChanged()
{
if (isLocActivated && exp->getEnabled()) {
@ -7145,7 +7151,7 @@ void LocallabBlur::usemaskChanged()
}
}
}
*/
void LocallabBlur::invblChanged()
{
const LocallabParams::LocallabSpot defSpot;

View File

@ -667,7 +667,7 @@ private:
Gtk::Label* const maskusable;
Gtk::Label* const maskunusable;
// Gtk::CheckButton* const usemask;
Gtk::CheckButton* const usemask;
Adjuster* const lnoiselow;
Adjuster* const levelthr;
Adjuster* const levelthrlow;
@ -682,6 +682,7 @@ private:
Adjuster* const noisechrof;
Adjuster* const noisechroc;
Adjuster* const noisechrodetail;
Gtk::Frame* const detailFrame;
Adjuster* const detailthr;
Adjuster* const adjblur;
Adjuster* const bilateral;

View File

@ -1284,7 +1284,7 @@ void ParamsEdited::initFrom(const std::vector<rtengine::procparams::ProcParams>&
locallab.spots.at(j).chroMethod = locallab.spots.at(j).chroMethod && pSpot.chroMethod == otherSpot.chroMethod;
locallab.spots.at(j).quamethod = locallab.spots.at(j).quamethod && pSpot.quamethod == otherSpot.quamethod;
locallab.spots.at(j).blurMethod = locallab.spots.at(j).blurMethod && pSpot.blurMethod == otherSpot.blurMethod;
// locallab.spots.at(j).usemask = locallab.spots.at(j).usemask && pSpot.usemask == otherSpot.usemask;
locallab.spots.at(j).usemask = locallab.spots.at(j).usemask && pSpot.usemask == otherSpot.usemask;
locallab.spots.at(j).levelthr = locallab.spots.at(j).levelthr && pSpot.levelthr == otherSpot.levelthr;
locallab.spots.at(j).lnoiselow = locallab.spots.at(j).lnoiselow && pSpot.lnoiselow == otherSpot.lnoiselow;
locallab.spots.at(j).levelthrlow = locallab.spots.at(j).levelthrlow && pSpot.levelthrlow == otherSpot.levelthrlow;
@ -4056,9 +4056,9 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.locallab.spots.at(i).blurMethod = mods.locallab.spots.at(i).blurMethod;
}
// if (locallab.spots.at(i).usemask) {
// toEdit.locallab.spots.at(i).usemask = mods.locallab.spots.at(i).usemask;
// }
if (locallab.spots.at(i).usemask) {
toEdit.locallab.spots.at(i).usemask = mods.locallab.spots.at(i).usemask;
}
if (locallab.spots.at(i).levelthr) {
toEdit.locallab.spots.at(i).levelthr = mods.locallab.spots.at(i).levelthr;
@ -6587,7 +6587,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) :
blMethod(v),
chroMethod(v),
quamethod(v),
// usemask(v),
usemask(v),
levelthr(v),
lnoiselow(v),
levelthrlow(v),
@ -7106,7 +7106,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v)
blMethod = v;
chroMethod = v;
quamethod = v;
// usemask = v;
usemask = v;
levelthr = v;
lnoiselow = v;
levelthrlow = v;

View File

@ -620,7 +620,7 @@ public:
bool blMethod;
bool chroMethod;
bool quamethod;
// bool usemask;
bool usemask;
bool levelthr;
bool lnoiselow;
bool levelthrlow;