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:
parent
183b20110b
commit
36cd2bc8ba
@ -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
889
rtengine/boxblural.h
Normal 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_ */
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1007,8 +1007,8 @@ enum ProcEventCode {
|
||||
EvlocallabwavCurvehue = 981,
|
||||
Evlocallablevelthr = 982,
|
||||
Evlocallablevelthrlow = 983,
|
||||
// Evlocallabusemask1 = 984,
|
||||
Evlocallablnoiselow = 984,
|
||||
Evlocallabusemask1 = 984,
|
||||
Evlocallablnoiselow = 985,
|
||||
NUMOFEVENTS
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -1011,7 +1011,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
|
||||
LUMINANCECURVE, //EvlocallabwavCurvehue
|
||||
LUMINANCECURVE, // Evlocallablevelthr
|
||||
LUMINANCECURVE, // Evlocallablevelthrlow
|
||||
// LUMINANCECURVE, //Evlocallabusemask1
|
||||
LUMINANCECURVE, //Evlocallabusemask1
|
||||
LUMINANCECURVE // Evlocallablnoiselow
|
||||
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -620,7 +620,7 @@ public:
|
||||
bool blMethod;
|
||||
bool chroMethod;
|
||||
bool quamethod;
|
||||
// bool usemask;
|
||||
bool usemask;
|
||||
bool levelthr;
|
||||
bool lnoiselow;
|
||||
bool levelthrlow;
|
||||
|
Loading…
x
Reference in New Issue
Block a user