diff --git a/rtdata/languages/default b/rtdata/languages/default
index 9e14fe764..5df352152 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -516,6 +516,8 @@ HISTORY_MSG_292;Black Level - Blue
HISTORY_MSG_293;Film Simulation
HISTORY_MSG_294;Film Simulation - Strength
HISTORY_MSG_295;Film Simulation - Film
+HISTORY_MSG_296;NR - Modulate luminance
+HISTORY_MSG_297;NR - Quality
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOTS;Snapshots
@@ -1176,6 +1178,14 @@ TP_DIRPYRDENOISE_LAB;Lab
TP_DIRPYRDENOISE_LDETAIL;Luminance Detail
TP_DIRPYRDENOISE_LM;Luminance only
TP_DIRPYRDENOISE_LUMA;Luminance
+TP_DIRPYRDENOISE_LCURVE;Luminance curve
+TP_DIRPYRDENOISE_CURVEEDITOR_L_TOOLTIP;Modulates action of 'Luminance' denoise
+TP_DIRPYRDENOISE_METHOD11;Quality
+TP_DIRPYRDENOISE_SHBI;Double
+TP_DIRPYRDENOISE_SHAL;Standard
+TP_DIRPYRDENOISE_SHALBI;High
+TP_DIRPYRDENOISE_SHALAL;ALL+ALL shrink
+TP_DIRPYRDENOISE_METHOD11_TOOLTIP;Quality can be adapted to the noise pattern: 1-Standard- 2-High\n 1->2 increase the noise reduction effect, but extend the processing time
TP_DIRPYRDENOISE_MEDMETHOD;Median method
TP_DIRPYRDENOISE_MEDTYPE;Median type
TP_DIRPYRDENOISE_MED;Median
diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc
index 83ecd459b..af444d189 100644
--- a/rtengine/FTblockDN.cc
+++ b/rtengine/FTblockDN.cc
@@ -61,7 +61,6 @@
#define blkrad 1 // radius of block averaging
#define epsilon 0.001f/(TS*TS) //tolerance
-
#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} }
#define med3(a0,a1,a2,a3,a4,a5,a6,a7,a8,median) { \
@@ -210,7 +209,7 @@ float media(float *elements, int N)
}
- void ImProcFunctions::RGB_denoise(Imagefloat * src, Imagefloat * dst, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp)
+ void ImProcFunctions::RGB_denoise(Imagefloat * src, Imagefloat * dst,Imagefloat * calclum, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp, const NoisCurve & dnNoisCurve, bool lldenoiseutili)
{
//#ifdef _DEBUG
MyTime t1e,t2e;
@@ -219,7 +218,43 @@ float media(float *elements, int N)
static MyMutex FftwMutex;
MyMutex::MyLock lock(FftwMutex);
+ int hei,wid;
+ float LLum,AAum,BBum;
+ float** lumcalc;
+
+ if(lldenoiseutili) {
+ hei=calclum->height;
+ wid=calclum->width;
+ TMatrix wprofi = iccStore->workingSpaceMatrix (params->icm.working);
+ double wpi[3][3] = {
+ {wprofi[0][0],wprofi[0][1],wprofi[0][2]},
+ {wprofi[1][0],wprofi[1][1],wprofi[1][2]},
+ {wprofi[2][0],wprofi[2][1],wprofi[2][2]}
+ };
+ lumcalc = new float*[hei];
+ for (int i=0; ir(ii,jj);
+ float GL = calclum->g(ii,jj);
+ float BL = calclum->b(ii,jj);
+ // determine luminance for noisecurve
+ float XL,YL,ZL;
+ Color::rgbxyz(RL,GL,BL,XL,YL,ZL,wpi);
+ Color::XYZ2Lab(XL, YL, ZL, LLum, AAum, BBum);
+ lumcalc[ii][jj]=LLum;
+ }
+ }
+
+ delete calclum;
+}
+// if(lldenoiseutili) printf("cest bon\n"); else printf("cest mauvais\n");
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -240,7 +275,8 @@ float media(float *elements, int N)
memcpy(dst->data,src->data,dst->width*dst->height*3*sizeof(float));
return;
}
-
+// printf("CALC=%f SRC=%f\n", calclum->r(30,50), src->r(30,50));//verify conversion colorspece is running
+
if (dnparams.luma!=0 || dnparams.chroma!=0 || dnparams.methodmed=="Lab" || dnparams.methodmed=="Lonly" ) {
perf=false;
if(dnparams.dmethod=="RGB") perf=true;//RGB mode
@@ -301,6 +337,7 @@ float media(float *elements, int N)
array2D tilemask_out(TS,TS);
const int border = MAX(2,TS/16);
+
#ifdef _OPENMP
#pragma omp parallel for
@@ -440,17 +477,26 @@ float media(float *elements, int N)
array2D Lin(width,height);
//wavelet denoised image
LabImage * labdn = new LabImage(width,height);
-
+ float* mad_LL = new float [height*width];
+ float** noisevarlum;
+ noisevarlum = new float*[height];
+ for (int i=0; i Ldetail(width,height,ARRAY2D_CLEAR_DATA);
//pixel weight
array2D totwt(width,height,ARRAY2D_CLEAR_DATA);//weight for combining DCT blocks
+ // init luma noisevarL
+ float noisevarL = (float) (SQR((dnparams.luma/125.0)*(1.+ dnparams.luma/25.0)));
+ // printf("nova=%f\n",noisevarL);
//TODO: implement using AlignedBufferMP
//fill tile from image; convert RGB to "luma/chroma"
if (isRAW) {//image is raw; use channel differences for chroma channels
if(!perf){//lab mode
- //modification Jacques feb 2013
+ //modification Jacques feb 2013 and july 2014
for (int i=tiletop/*, i1=0*/; ir(i,j);
float G_ = gain*src->g(i,j);
float B_ = gain*src->b(i,j);
+ float Llum,alum,blum;
+
+ /* if(dnNoisCurve) {
+ //conversion colorspace to determine luminance with no gamma
+ float RL = calclum->r(i,j);
+ float GL = calclum->g(i,j);
+ float BL = calclum->b(i,j);
+ // determine luminance for noisecurve
+ float XL,YL,ZL;
+ Color::rgbxyz(RL,GL,BL,XL,YL,ZL,wp);
+ Color::XYZ2Lab(XL, YL, ZL, Llum, alum, blum);
+ }
+ */
+ if(dnNoisCurve) {
+ Llum=lumcalc[i][j];
+ }
//modify arbitrary data for Lab..I have test : nothing, gamma 2.6 11 - gamma 4 5 - gamma 5.5 10
//we can put other as gamma g=2.6 slope=11, etc.
// but noting to do with real gamma !!!: it's only for data Lab # data RGB
@@ -490,6 +552,21 @@ float media(float *elements, int N)
//convert to Lab
Color::XYZ2Lab(X, Y, Z, L, a, b);
+ float noiseluma=(float) dnparams.luma;
+
+ if(dnNoisCurve) {
+ float kN=Llum;//with no gamma and take into account working profile
+ float epsi=0.01f;
+ if(kN<2.f) kN=2.f;//avoid divided by zero
+ if(kN>32768.f) kN=32768.f; // not strictly necessary
+ float kinterm=epsi+ dnNoisCurve.lutNoisCurve[(kN/32768.f)*500.f];
+ float ki=kinterm*100.f;
+ ki+=noiseluma;
+ noiseluma += 1.f;
+ noisevarlum[i1][j1]= SQR((ki/125.f)*(1.f+ki/25.f));
+ }
+ noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f));
+
labdn->L[i1][j1] = L;
labdn->a[i1][j1] = a;
labdn->b[i1][j1] = b;
@@ -499,6 +576,7 @@ float media(float *elements, int N)
}
}
else {//RGB mode
+
for (int i=tiletop/*, i1=0*/; ir(i,j);
float Y = gain*src->g(i,j);
float Z = gain*src->b(i,j);
-
+ //conversion colorspace to determine luminance with no gamma
+ float Llum,alum,blum;
+ /* if(dnNoisCurve) {
+ float RL = calclum->r(i,j);
+ float GL = calclum->g(i,j);
+ float BL = calclum->b(i,j);
+ float XL,YL,ZL;
+ Color::rgbxyz(RL,GL,BL,XL,YL,ZL,wp);
+ Color::XYZ2Lab(XL, YL, ZL, Llum, alum, blum);
+ }
+ */
+ if(dnNoisCurve) {
+ Llum=lumcalc[i][j];
+ }
X = X<65535.0f ? gamcurve[X] : (Color::gamma((double)X/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f);
Y = Y<65535.0f ? gamcurve[Y] : (Color::gamma((double)Y/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f);
Z = Z<65535.0f ? gamcurve[Z] : (Color::gamma((double)Z/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)*32768.0f);
-
+ float noiseluma=(float) dnparams.luma;
+ if(dnNoisCurve) {
+ // float noiseluma=(float) dnparams.luma;
+ float kN=Llum;
+ float epsi=0.01f;
+ if(kN<2.f) kN=2.f;
+ if(kN>32768.f) kN=32768.f;
+ float kinterm=epsi + dnNoisCurve.lutNoisCurve[(kN/32768.f)*500.f];
+ float ki=kinterm*100.f;
+ ki+=noiseluma;
+ noiseluma += 1.f;
+ noisevarlum[i1][j1]= SQR((ki/125.f)*(1.f+ki/25.f));
+ }
+ noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f));
+
labdn->L[i1][j1] = Y;
labdn->a[i1][j1] = (X-Y);
labdn->b[i1][j1] = (Y-Z);
@@ -523,12 +628,17 @@ float media(float *elements, int N)
}
}
+
} else {//image is not raw; use Lab parametrization
for (int i=tiletop/*, i1=0*/; ir(i,j) ;//for luminance denoise curve
+ float gLum=src->g(i,j) ;
+ float bLum=src->b(i,j) ;
+
//use gamma sRGB, not good if TIF (JPG) Output profil not with gamma sRGB (eg : gamma =1.0, or 1.8...)
//very difficult to solve !
// solution ==> save TIF with gamma sRGB and re open
@@ -547,6 +657,30 @@ float media(float *elements, int N)
//convert Lab
Color::XYZ2Lab(X, Y, Z, L, a, b);
+ float Llum,alum,blum;
+ if(dnNoisCurve) {
+ float XL,YL,ZL;
+ Color::rgbxyz(rLum,gLum,bLum,XL,YL,ZL,wp);
+ Color::XYZ2Lab(XL, YL, ZL, Llum, alum, blum);
+ }
+ float noiseluma=(float) dnparams.luma;
+
+ if(dnNoisCurve) {
+ // float noiseluma=(float) dnparams.luma;
+ float kN=Llum;
+ float epsi=0.01f;
+
+ if(kN<2.f) kN=2.f;
+ if(kN>32768.f) kN=32768.f;
+ float kinterm=epsi + dnNoisCurve.lutNoisCurve[(kN/32768.f)*500.f];
+ float ki=kinterm*100.f;
+ ki+=noiseluma;
+ noiseluma += 1.f;
+ // noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f));
+ noisevarlum[i1][j1]=SQR((ki/125.f)*(1.f+ki/25.f));
+ }
+ noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f));
+
labdn->L[i1][j1] = L;
labdn->a[i1][j1] = a;
labdn->b[i1][j1] = b;
@@ -558,8 +692,7 @@ float media(float *elements, int N)
}
}
}
-
-
+ // printf("OK\n");
//initial impulse denoise
if (dnparams.luma>0.01) {
impulse_nr (labdn, float(MIN(50.0,dnparams.luma))/20.0f);
@@ -572,24 +705,23 @@ float media(float *elements, int N)
//and whether to subsample the image after wavelet filtering. Subsampling is coded as
//binary 1 or 0 for each level, eg subsampling = 0 means no subsampling, 1 means subsample
//the first level only, 7 means subsample the first three levels, etc.
- float noisevarL = (float) (SQR((dnparams.luma/125.0)*(1.+ dnparams.luma/25.0)));
- //printf("noisL=%f \n",noisevarL);
+ // float noisevarL = (float) (SQR((dnparams.luma/125.0)*(1.+ dnparams.luma/25.0)));
float interm_med= (float) dnparams.chroma/10.0;
- //printf("inter=%f\n",interm_med);
+ // printf("inter=%f\n",interm_med);
float intermred, intermblue;
- if(dnparams.redchro > 0.) intermred=0.0014f* (float)SQR(dnparams.redchro); else intermred= (float) dnparams.redchro/7.0;//increase slower than linear for more sensit
+ if(dnparams.redchro > 0.) intermred=0.00014f* (float)SQR(dnparams.redchro); else intermred= (float) dnparams.redchro/7.0;//increase slower than linear for more sensit
float intermred2=(float) dnparams.redchro/7.0;
- if(dnparams.bluechro > 0.) intermblue=0.0014f*(float) SQR(dnparams.bluechro); else intermblue= (float)dnparams.bluechro/7.0;//increase slower than linear
+ if(dnparams.bluechro > 0.) intermblue=0.00014f*(float) SQR(dnparams.bluechro); else intermblue= (float)dnparams.bluechro/7.0;//increase slower than linear
float intermblue2=(float) dnparams.bluechro/7.0;
//adjust noise ab in function of sliders red and blue
- float realred = interm_med + intermred; if (realred < 0.f) realred=0.01f;
- float realred2 = interm_med + intermred2; if (realred2 < 0.f) realred2=0.01f;
+ float realred = interm_med + intermred; if (realred < 0.f) realred=0.001f;
+ float realred2 = interm_med + intermred2; if (realred2 < 0.f) realred2=0.001f;
float noisevarab_r = SQR(realred);
- float realblue = interm_med + intermblue; if (realblue < 0.f) realblue=0.01f;
- float realblue2 = interm_med + intermblue2; if (realblue2 < 0.f) realblue2=0.01f;
+ float realblue = interm_med + intermblue; if (realblue < 0.f) realblue=0.001f;
+ float realblue2 = interm_med + intermblue2; if (realblue2 < 0.f) realblue2=0.001f;
float noisevarab_b = SQR(realblue);
bool execwavelet=true;
- if(noisevarL < 0.00007f && interm_med < 0.1f && dnparams.median && (dnparams.methodmed=="Lab" || dnparams.methodmed=="Lonly")) execwavelet=false;//do not exec wavelet if sliders luminance and chroma are very small and median need
+ if(noisevarL < 0.000007f && interm_med < 0.05f && dnparams.median && (dnparams.methodmed=="Lab" || dnparams.methodmed=="Lonly")) execwavelet=false;//do not exec wavelet if sliders luminance and chroma are very small and median need
//we considered user don't want wavelet
if(execwavelet) {//gain time if user choose only median sliders L <=1 slider chrom master < 1
{ // enclosing this code in a block frees about 120 MB before allocating 20 MB after this block (measured with D700 NEF)
@@ -605,15 +737,35 @@ float media(float *elements, int N)
else if( maxreal < 15.f)levwav=7;
else levwav=8;//maximum ==> I have increase Maxlevel in cplx_wavelet_dec.h from 8 to 9
+ int schoice=0;//shrink method
+ if(dnparams.smethod=="shal") schoice=0;
+ // else if(dnparams.smethod=="shbi") schoice=1;
+ else if(dnparams.smethod=="shalbi") schoice=2;
+ // else if(dnparams.smethod=="shalal") schoice=3;
+ // else if(dnparams.smethod=="shbibi") schoice=4;
+
// if (settings->verbose) printf("levwavelet=%i noisevarA=%f noisevarB=%f \n",levwav, noisevarab_r, noisevarab_b );
Ldecomp = new wavelet_decomposition (labdn->data, labdn->W, labdn->H, levwav/*maxlevels*/, 0/*subsampling*/ );
adecomp = new wavelet_decomposition (labdn->data+datalen, labdn->W, labdn->H,levwav, 1 );
bdecomp = new wavelet_decomposition (labdn->data+2*datalen, labdn->W, labdn->H, levwav, 1 );
- if(enhance_denoise) WaveletDenoiseAll_BiShrink(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarab_r, noisevarab_b,labdn);//enhance mode
- else; WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarab_r, noisevarab_b,labdn);//
-
+ if(schoice==0) WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, width, height, mad_LL, noisevarab_r, noisevarab_b,labdn, lldenoiseutili, dnNoisCurve);//enhance mode
+ // if(schoice==1) WaveletDenoiseAll_BiShrink(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, width, height, mad_LL, noisevarab_r, noisevarab_b,labdn, lldenoiseutili);
+ if(schoice==2) {
+ WaveletDenoiseAll_BiShrink(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, width, height, mad_LL, noisevarab_r, noisevarab_b,labdn, lldenoiseutili, dnNoisCurve);//enhance mode
+ WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, width, height, mad_LL, noisevarab_r, noisevarab_b,labdn, lldenoiseutili, dnNoisCurve);
+ }
+ /* if(schoice==3) {
+ WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, width, height, mad_LL, noisevarab_r, noisevarab_b,labdn, lldenoiseutili);//enhance mode
+ WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, width, height, mad_LL, noisevarab_r, noisevarab_b,labdn, lldenoiseutili);
+ }
+ if(schoice==4) {
+ WaveletDenoiseAll_BiShrink(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, width, height, mad_LL, noisevarab_r, noisevarab_b,labdn, lldenoiseutili);//enhance mode
+ WaveletDenoiseAll_BiShrink(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, width, height, mad_LL, noisevarab_r, noisevarab_b,labdn, lldenoiseutili);
+ }
+ */
+
Ldecomp->reconstruct(labdn->data);
delete Ldecomp;
adecomp->reconstruct(labdn->data+datalen);
@@ -630,6 +782,7 @@ float media(float *elements, int N)
impulse_nr (labdn, MIN(50.0f,(float)dnparams.luma)/20.0f);
}
//PF_correct_RT(dst, dst, defringe.radius, defringe.threshold);
+
int metchoice=0;
if(dnparams.methodmed=="Lonly") metchoice=1;
@@ -1121,6 +1274,11 @@ float media(float *elements, int N)
delete labdn;
// delete noiseh;
+ for (int i=0; iverbose) {
@@ -1480,7 +1643,7 @@ SSEFUNCTION void ImProcFunctions::RGBtile_denoise (float * fLblox, int hblproc,
SSEFUNCTION void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
- wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi)
+ wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float **noisevarlum, int width, int height, float *mad_LL, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve)
{
int maxlvl = WaveletCoeffs_L.maxlevel();
const float eps = 0.01f;
@@ -1496,7 +1659,10 @@ SSEFUNCTION void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decompositi
int Wlvl_L = WaveletCoeffs_L.level_W(lvl);
int Hlvl_L = WaveletCoeffs_L.level_H(lvl);
-
+
+ if(Wlvl_L!=width) Wlvl_L=width;
+ if(Hlvl_L!=height) Hlvl_L=height;
+
int Wlvl_ab = WaveletCoeffs_a.level_W(lvl);
int Hlvl_ab = WaveletCoeffs_a.level_H(lvl);
@@ -1517,7 +1683,12 @@ SSEFUNCTION void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decompositi
int Wlvl_L = WaveletCoeffs_L.level_W(lvl);
int Hlvl_L = WaveletCoeffs_L.level_H(lvl);
-
+ // printf("w=%d WL=%d\n",width, Wlvl_L);
+ // printf("h=%d HL=%d\n",height, Hlvl_L);
+
+ if(Wlvl_L!=width) Wlvl_L=width;
+ if(Hlvl_L!=height) Hlvl_L=height;
+
int Wlvl_ab = WaveletCoeffs_a.level_W(lvl);
int Hlvl_ab = WaveletCoeffs_a.level_H(lvl);
@@ -1530,7 +1701,7 @@ SSEFUNCTION void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decompositi
if (lvl==maxlvl-1) {
ShrinkAll(WavCoeffs_L, WavCoeffs_a, WavCoeffs_b, lvl, Wlvl_L, Hlvl_L, Wlvl_ab, Hlvl_ab,
- skip_L, skip_ab, noisevar_L, noisevar_abr, noisevar_abb, noi, mada[lvl], madb[lvl], madL[lvl], true);
+ skip_L, skip_ab, noisevar_L, noisevarlum, width, height, mad_LL, noisevar_abr, noisevar_abb, noi, lldenoiseutili, dnNoisCurve, mada[lvl], madb[lvl], madL[lvl], true);
} else {
@@ -1541,13 +1712,14 @@ SSEFUNCTION void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decompositi
//simple wavelet shrinkage
float * sfave = new float[Wlvl_L*Hlvl_L];
float * WavCoeffsLtemp = new float[Hlvl_ab*Wlvl_ab];
+ // float * mad_L = new float[Wlvl_L*Hlvl_L];
// array2D edge(Wlvl_L,Hlvl_L);
//printf("\n level=%d \n",lvl);
for (int dir=1; dir<4; dir++) {
- float mad_L = madL[lvl][dir-1];
+ float mad_Lr = madL[lvl][dir-1];
float mad_a = noisevar_abr*mada[lvl][dir-1];
float mad_b = noisevar_abb*madb[lvl][dir-1];
@@ -1559,14 +1731,14 @@ SSEFUNCTION void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decompositi
//float skip_ab_ratio = WaveletCoeffs_a.level_stride(lvl+1)/skip_ab;
// float skip_L_ratio = WaveletCoeffs_L.level_stride(lvl+1)/skip_L;
- if (noisevar_abr>0.01f || noisevar_abb>0.01f) {
+ if (noisevar_abr>0.001f || noisevar_abb>0.001f) {
for(int i=0;i0.01f) {
- mad_L *= noisevar_L*5.f/(lvl+1);
+ if (noisevar_L>0.00001f) {
+ if (!lldenoiseutili && dnNoisCurve.nonzero < 7.f ) {
+ for (int i=0; i= 7.f) {
+ for (int i=0; i (edge, edge, buffer, Wlvl_L, Hlvl_L, 1<<(lvl+1), false /*multiThread*/);
+ //gaussHorizontal (edge, edge, buffer, Wlvl_L, Hlvl_L, 1<<(lvl+1), false);
//gaussVertical (edge, edge, buffer, Wlvl_L, Hlvl_L, 1<<(lvl+1), false);
-
- boxblur(sfave, sfave, lvl+2, lvl+2, Wlvl_L, Hlvl_L);//increase smoothness by locally averaging shrinkage
+
+ boxblur(sfave, sfave, lvl+2, lvl+2, Wlvl_L, Hlvl_L);//increase smoothness by locally averaging shrinkage
#ifdef __SSE2__
__m128 tempLv;
@@ -1677,25 +1875,26 @@ SSEFUNCTION void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decompositi
for (int i=0; i 582=max
float mad_b = madb*noisevar_abb;
+ // printf("noisevarabr=%f\n",noisevar_abr);
- if (noisevar_abr>0.01f || noisevar_abb>0.01f) {
+ if (noisevar_abr>0.001f || noisevar_abb>0.001f ) {
for(int i=0;iverbose) printf("noisevar=%f dnzero=%f \n",noisevar_L, dnNoisCurve.nonzero);
+
+ if (noisevar_L>0.00001f) {
+ if (!lldenoiseutili || dnNoisCurve.nonzero < 7.f ){//under 7 quasi no action
+ // printf("sans\n");
+ for (int i=0; i= 7.f) {//printf("avec\n");
- if (noisevar_L>0.01f) {
+ for (int i=0; i& llcurvePoints, LUTf & Noisecurve,int skip){
+ bool needed;
+ DiagonalCurve* dCurve = NULL;
+ LUTf dCcurve(65536,0);
+
+ float val;
+ for (int i=0; i<32768; i++) {
+ dCcurve[i] = (float)i / 32767.0;
+ }
+
+ needed = false;
+ if (!llcurvePoints.empty() && llcurvePoints[0]!=0) {
+ dCurve = new DiagonalCurve (llcurvePoints, CURVES_MIN_POLY_POINTS/skip);
+
+ if (dCurve && !dCurve->isIdentity())
+ {needed = true;lldenoiseutili=true;}
+ }
+ fillCurveArray(dCurve, Noisecurve, skip, needed);
+ //Noisecurve.dump("Noise");
+
+ if (dCurve) {
+ delete dCurve;
+ dCurve = NULL;
+ }
+}
+
void CurveFactory::curveBW (
const std::vector& curvePointsbw, const std::vector& curvePointsbw2,
@@ -1153,6 +1180,38 @@ void OpacityCurve::Set(const std::vector &curvePoints) {
}
}
+void NoisCurve::Reset() {
+ lutNoisCurve.reset();
+}
+
+void NoisCurve::Set(const Curve *pCurve) {
+ if (pCurve->isIdentity()) {
+ lutNoisCurve.reset(); // raise this value if the quality suffers from this number of samples
+ return;
+ }
+ lutNoisCurve(501); // raise this value if the quality suffers from this number of samples
+ nonzero=0.f;
+ for (int i=0; i<501; i++) {
+ lutNoisCurve[i] = pCurve->getVal(double(i)/500.);
+ if(lutNoisCurve[i] < 0.01f) lutNoisCurve[i]=0.01f;//avoid 0.f for wavelet : under 0.01f quasi no action for each value
+ nonzero+=lutNoisCurve[i];}//minima for Wavelet about 6.f or 7.f quasi no action
+ //lutNoisCurve.dump("Nois");
+}
+
+void NoisCurve::Set(const std::vector &curvePoints, bool &lldenoiseutili) {
+ FlatCurve* tcurve = NULL;
+
+ if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0]setIdentityValue(0.);
+ }
+ if (tcurve) {
+ Set(tcurve);lldenoiseutili=true;
+ delete tcurve;
+ tcurve = NULL;
+ }
+}
+
void ColorGradientCurve::Reset() {
lut1.reset();
lut2.reset();
diff --git a/rtengine/curves.h b/rtengine/curves.h
index dc2a5b7eb..5e0ecbc7b 100644
--- a/rtengine/curves.h
+++ b/rtengine/curves.h
@@ -198,6 +198,7 @@ class CurveFactory {
static void curveCL ( bool & clcutili, const std::vector& clcurvePoints, LUTf & clCurve, LUTu & histogramcl, LUTu & outBeforeCLurveHistogram, int skip);
static void curveToningCL ( bool & clctoningutili, const std::vector& clcurvePoints, LUTf & clToningCurve, int skip);
static void curveToningLL ( bool & llctoningutili, const std::vector& llcurvePoints, LUTf & llToningCurve, int skip);
+ static void denoiseLL ( bool & lldenoiseutili, const std::vector& llcurvePoints, LUTf & Noisecurve,int skip);
static void complexsgnCurve ( float adjustr, bool & autili, bool & butili, bool & ccutili, bool & clcutili, double saturation, double rstprotection, const std::vector& acurvePoints,
const std::vector& bcurvePoints,const std::vector& cccurvePoints,const std::vector& lccurvePoints, LUTf & aoutCurve, LUTf & boutCurve, LUTf & satCurve, LUTf & lhskCurve,
@@ -349,6 +350,18 @@ class OpacityCurve {
operator bool (void) const { return lutOpacityCurve; }
};
+class NoisCurve {
+ public:
+ LUTf lutNoisCurve; // 0xffff range
+ float nonzero;
+ virtual ~NoisCurve() {};
+
+ void Reset();
+ void Set(const Curve *pCurve);
+ void Set(const std::vector &curvePoints, bool &lldenoiseutili);
+
+ operator bool (void) const { return lutNoisCurve; }
+};
class ColorGradientCurve {
public:
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index d62efcfcf..3e5804235 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -5,6 +5,7 @@
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+ * 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.
*
@@ -155,14 +156,28 @@ void Crop::update (int todo) {
parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw );
//ColorTemp::CAT02 (origCrop, ¶ms) ;
- //parent->imgsrc->convertColorSpace(origCrop, params.icm);
-
+ Imagefloat *calclum;//for Luminance denoise curve
+ NoisCurve dnNoisCurve;
+ bool lldenoiseutili=false;
+ params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoiseutili);
+ if(lldenoiseutili && skip==1 && params.dirpyrDenoise.enabled) {//only allocate memory if enabled and skip
+ calclum = new Imagefloat (cropw, croph);//for Luminance denoise curve
+ if(origCrop != calclum)
+ memcpy(calclum->data,origCrop->data,origCrop->width*origCrop->height*3*sizeof(float));
+
+ parent->imgsrc->convertColorSpace(calclum, params.icm, parent->currWB, params.raw);//for denoise luminance curve
+ }
if (todo & M_LINDENOISE) {
- if (skip==1 && params.dirpyrDenoise.enabled)
- parent->ipf.RGB_denoise(origCrop, origCrop, parent->imgsrc->isRAW(), /*Roffset,*/ params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp());
+ if (skip==1 && params.dirpyrDenoise.enabled) {
+
+ parent->ipf.RGB_denoise(origCrop, origCrop, calclum, parent->imgsrc->isRAW(), /*Roffset,*/ params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve,lldenoiseutili);
}
+ }
+ // delete calclum;
+
parent->imgsrc->convertColorSpace(origCrop, params.icm, parent->currWB, params.raw);
- }
+
+ }
// has to be called after setCropSizes! Tools prior to this point can't handle the Edit mechanism, but that shouldn't be a problem.
createBuffer(cropw, croph);
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index c99a0ac53..732ef095d 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -46,7 +46,7 @@ ImProcCoordinator::ImProcCoordinator ()
clcurve(65536,0),
clToningcurve(65536,0),
cl2Toningcurve(65536,0),
-
+ Noisecurve(65536,0),
vhist16(65536),vhist16bw(65536),
lhist16(65536), lhist16Cropped(65536),
lhist16CAM(65536), lhist16CroppedCAM(65536),
@@ -83,7 +83,7 @@ ImProcCoordinator::ImProcCoordinator ()
pW(-1), pH(-1),
plistener(NULL), imageListener(NULL), aeListener(NULL), hListener(NULL),acListener(NULL), abwListener(NULL),actListener(NULL),
- resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false),utili(false),autili(false),
+ resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false),utili(false),autili(false),lldenoiseutili(false),
butili(false),ccutili(false),cclutili(false),clcutili(false),fullw(1),fullh(1)
{}
@@ -265,13 +265,27 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
imgsrc->getImage (currWB, tr, orig_prev, pp, params.toneCurve, params.icm, params.raw);
//ColorTemp::CAT02 (orig_prev, ¶ms) ;
- //imgsrc->convertColorSpace(orig_prev, params.icm, params.raw);
-
+ Imagefloat *calclum ;
+ lldenoiseutili=false;
+ params.dirpyrDenoise.getCurves(dnNoisCurve,lldenoiseutili);
+ if(lldenoiseutili && scale==1 && params.dirpyrDenoise.enabled ){//only allocate memory if enabled and scale=1
+ calclum = new Imagefloat (pW, pH);//for Luminance denoise curve
+ if(orig_prev != calclum)
+ memcpy(calclum->data,orig_prev->data,orig_prev->width*orig_prev->height*3*sizeof(float));
+
+ imgsrc->convertColorSpace(calclum, params.icm, currWB, params.raw);//claculate values after colorspace conversion
+ }
+
if (todo & M_LINDENOISE) {
- //printf("denoising!\n");
- if (scale==1 && params.dirpyrDenoise.enabled)
- ipf.RGB_denoise(orig_prev, orig_prev, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp());
- }
+
+ if (scale==1 && params.dirpyrDenoise.enabled) {
+
+ ipf.RGB_denoise(orig_prev, orig_prev, calclum, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve, lldenoiseutili);
+
+ }
+ }
+ // delete calclum;
+
imgsrc->convertColorSpace(orig_prev, params.icm, currWB, params.raw);
ipf.firstAnalysis (orig_prev, ¶ms, vhist16, imgsrc->getGamma());
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index d646423ef..52bb630fc 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -93,6 +93,7 @@ class ImProcCoordinator : public StagedImageProcessor {
LUTf clcurve;
LUTf clToningcurve;
LUTf cl2Toningcurve;
+ LUTf Noisecurve;
LUTu vhist16,vhist16bw;
LUTu lhist16,lhist16Cropped;
@@ -119,11 +120,12 @@ class ImProcCoordinator : public StagedImageProcessor {
bool ccutili;
bool cclutili;
bool clcutili;
-
+ bool lldenoiseutili;
ToneCurve customToneCurve1;
ToneCurve customToneCurve2;
ColorGradientCurve ctColorCurve;
OpacityCurve ctOpacityCurve;
+ NoisCurve dnNoisCurve;
ColorAppearance customColCurve1;
ColorAppearance customColCurve2;
ColorAppearance customColCurve3;
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index 3d70e5a18..d907bcbe1 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -259,7 +259,7 @@ class ImProcFunctions {
//void RGB_InputTransf(Imagefloat * src, LabImage * dst, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe);
//void RGB_OutputTransf(LabImage * src, Imagefloat * dst, const procparams::DirPyrDenoiseParams & dnparams);
//void output_tile_row (float *Lbloxrow, float ** Lhipassdn, float ** tilemask, int height, int width, int top, int blkrad );
- void RGB_denoise(Imagefloat * src, Imagefloat * dst, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp);
+ void RGB_denoise(Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp,const NoisCurve & ctNoisCurve , bool lldenoiseutili);
void RGBtile_denoise (float * fLblox, int hblproc, float noisevar_L, float * nbrwt, float * blurbuffer ); //for DCT
void RGBoutput_tile_row (float *Lbloxrow, float ** Ldetail, float ** tilemask_out, int height, int width, int top );
//void WaveletDenoise(cplx_wavelet_decomposition &DualTreeCoeffs, float noisevar );
@@ -267,10 +267,10 @@ class ImProcFunctions {
// void WaveletDenoiseAll(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
// wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_ab, wavelet_decomposition &wch, NoiImage * noi );
void WaveletDenoiseAll(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
- wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi );
+ wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float **noisevarlum, int width, int height, float *mad_LL, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve);
void WaveletDenoiseAll_BiShrink(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
- wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi);
+ wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float **noisevarlum, int width, int height, float *mad_LL, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve);
//void BiShrink(float * ReCoeffs, float * ImCoeffs, float * ReParents, float * ImParents,
// int W, int H, int level, int padding, float noisevar);
//void Shrink(float ** WavCoeffs, int W, int H, int level, float noisevar);
@@ -278,7 +278,7 @@ class ImProcFunctions {
// int W_L, int H_L, int W_ab, int H_ab, int W_h, int H_h, int skip_L, int skip_ab, int skip_h, float noisevar_L, float noisevar_ab, float **WavCoeffs_h, LabImage * noi);
void ShrinkAll(float ** WavCoeffs_L, float ** WavCoeffs_a, float ** WavCoeffs_b, int level,
- int W_L, int H_L, int W_ab, int H_ab, int skip_L, int skip_ab, float noisevar_L, float noisevar_abr, float noisevar_abb,LabImage * noi, float * madaa = NULL, float * madab = NULL, float * madaL = NULL, bool madCalculated = false);
+ int W_L, int H_L, int W_ab, int H_ab, int skip_L, int skip_ab, float noisevar_L, float **noisevarlum, int width, int height, float *mad_LL, float noisevar_abr, float noisevar_abb,LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve, float * madaa = NULL, float * madab = NULL, float * madaL = NULL, bool madCalculated= false);
float MadMax(float * HH_Coeffs, int &max, int datalen);
float Mad(float * HH_Coeffs, int datalen, int * histo);
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index 74f5d8751..f6592a714 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -320,6 +320,9 @@ enum ProcEvent {
EvFilmSimulationEnabled=292,
EvFilmSimulationStrength=293,
EvFilmSimulationFilename=294,
+ EvDPDNLCurve=295,
+ EvDPDNsmet=296,
+
NUMOFEVENTS
};
}
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 1e1ff50ff..91ac6dad5 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -414,6 +414,48 @@ void ColorToningParams::getCurves(ColorGradientCurve &colorCurveLUT, OpacityCurv
}
}
+
+DirPyrDenoiseParams::DirPyrDenoiseParams () {
+ setDefault ();
+}
+
+void DirPyrDenoiseParams::getDefaultNoisCurve(std::vector &curve) {
+ double v[8]={ 0.05, 0.15, 0.35, 0.35,
+ 0.55, 0.04, 0.35, 0.35};
+ curve.resize(9);
+ curve.at(0 ) = double(FCT_MinMaxCPoints);
+ for (size_t i=1; i llCurve;
+ llCurve = this->lcurve;
+ lcurveLUT.Set(llCurve, lldenoiseutili);
+}
+
+
+
ProcParams::ProcParams () {
setDefaults ();
@@ -602,12 +644,14 @@ void ProcParams::setDefaults () {
defringe.huecurve.at(22) = 0.;
defringe.huecurve.at(23) = 0.35;
defringe.huecurve.at(24) = 0.35;
-
+/*
dirpyrDenoise.enabled = false;
dirpyrDenoise.enhance = false;
// dirpyrDenoise.perform = false;
dirpyrDenoise.median = true;
dirpyrDenoise.luma = 0;
+ dirpyrDenoise.lcurve.clear ();
+ dirpyrDenoise.lcurve.push_back(DCT_Linear);
dirpyrDenoise.Ldetail = 50;
dirpyrDenoise.chroma = 15;
dirpyrDenoise.redchro = 0;
@@ -615,10 +659,11 @@ void ProcParams::setDefaults () {
dirpyrDenoise.gamma = 1.7;
dirpyrDenoise.passes = 1;
dirpyrDenoise.dmethod = "RGB";
+ dirpyrDenoise.smethod = "shal";
dirpyrDenoise.medmethod = "soft";
dirpyrDenoise.methodmed = "none";
dirpyrDenoise.rgbmethod = "soft";
-
+*/
epd.enabled = false;
epd.strength = 0.25;
epd.edgeStopping = 1.4;
@@ -1213,6 +1258,7 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
if (!pedited || pedited->dirpyrDenoise.Ldetail) keyFile.set_double ("Directional Pyramid Denoising", "Ldetail", dirpyrDenoise.Ldetail);
if (!pedited || pedited->dirpyrDenoise.chroma) keyFile.set_double ("Directional Pyramid Denoising", "Chroma", dirpyrDenoise.chroma);
if (!pedited || pedited->dirpyrDenoise.dmethod) keyFile.set_string ("Directional Pyramid Denoising", "Method", dirpyrDenoise.dmethod);
+ if (!pedited || pedited->dirpyrDenoise.smethod) keyFile.set_string ("Directional Pyramid Denoising", "SMethod", dirpyrDenoise.smethod);
if (!pedited || pedited->dirpyrDenoise.medmethod) keyFile.set_string ("Directional Pyramid Denoising", "MedMethod", dirpyrDenoise.medmethod);
if (!pedited || pedited->dirpyrDenoise.rgbmethod) keyFile.set_string ("Directional Pyramid Denoising", "RGBMethod", dirpyrDenoise.rgbmethod);
if (!pedited || pedited->dirpyrDenoise.methodmed) keyFile.set_string ("Directional Pyramid Denoising", "MethodMed", dirpyrDenoise.methodmed);
@@ -1220,6 +1266,10 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
if (!pedited || pedited->dirpyrDenoise.bluechro)keyFile.set_double ("Directional Pyramid Denoising", "Bluechro", dirpyrDenoise.bluechro);
if (!pedited || pedited->dirpyrDenoise.gamma) keyFile.set_double ("Directional Pyramid Denoising", "Gamma", dirpyrDenoise.gamma);
if (!pedited || pedited->dirpyrDenoise.passes) keyFile.set_integer ("Directional Pyramid Denoising", "Passes", dirpyrDenoise.passes);
+ if (!pedited || pedited->dirpyrDenoise.lcurve) {
+ Glib::ArrayHandle lcurve = dirpyrDenoise.lcurve;
+ keyFile.set_double_list("Directional Pyramid Denoising", "LCurve", lcurve);
+ }
//Save epd.
if (!pedited || pedited->epd.enabled) keyFile.set_boolean ("EPD", "Enabled", epd.enabled);
@@ -1874,9 +1924,11 @@ if (keyFile.has_group ("Directional Pyramid Denoising")) {//TODO: No longer an a
if (keyFile.has_key ("Directional Pyramid Denoising", "Ldetail")) { dirpyrDenoise.Ldetail = keyFile.get_double ("Directional Pyramid Denoising", "Ldetail"); if (pedited) pedited->dirpyrDenoise.Ldetail = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "Chroma")) { dirpyrDenoise.chroma = keyFile.get_double ("Directional Pyramid Denoising", "Chroma"); if (pedited) pedited->dirpyrDenoise.chroma = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "Method")) {dirpyrDenoise.dmethod = keyFile.get_string ("Directional Pyramid Denoising", "Method"); if (pedited) pedited->dirpyrDenoise.dmethod = true; }
+ if (keyFile.has_key ("Directional Pyramid Denoising", "SMethod")) {dirpyrDenoise.smethod = keyFile.get_string ("Directional Pyramid Denoising", "SMethod"); if (pedited) pedited->dirpyrDenoise.smethod = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "MedMethod")) {dirpyrDenoise.medmethod = keyFile.get_string ("Directional Pyramid Denoising", "MedMethod"); if (pedited) pedited->dirpyrDenoise.medmethod = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "MethodMed")) {dirpyrDenoise.methodmed = keyFile.get_string ("Directional Pyramid Denoising", "MethodMed"); if (pedited) pedited->dirpyrDenoise.methodmed = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "RGBMethod")) {dirpyrDenoise.rgbmethod = keyFile.get_string ("Directional Pyramid Denoising", "RGBMethod"); if (pedited) pedited->dirpyrDenoise.rgbmethod = true; }
+ if (keyFile.has_key ("Directional Pyramid Denoising", "LCurve")) {dirpyrDenoise.lcurve = keyFile.get_double_list ("Directional Pyramid Denoising", "LCurve"); if (pedited) pedited->dirpyrDenoise.lcurve = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "Redchro")) { dirpyrDenoise.redchro = keyFile.get_double ("Directional Pyramid Denoising", "Redchro"); if (pedited) pedited->dirpyrDenoise.redchro = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "Bluechro")) { dirpyrDenoise.bluechro = keyFile.get_double ("Directional Pyramid Denoising", "Bluechro"); if (pedited) pedited->dirpyrDenoise.bluechro = true; }
@@ -2385,9 +2437,11 @@ bool ProcParams::operator== (const ProcParams& other) {
&& dirpyrDenoise.median == other.dirpyrDenoise.median
// && dirpyrDenoise.perform == other.dirpyrDenoise.perform
&& dirpyrDenoise.luma == other.dirpyrDenoise.luma
+ && dirpyrDenoise.lcurve == other.dirpyrDenoise.lcurve
&& dirpyrDenoise.Ldetail == other.dirpyrDenoise.Ldetail
&& dirpyrDenoise.chroma == other.dirpyrDenoise.chroma
&& dirpyrDenoise.dmethod == other.dirpyrDenoise.dmethod
+ && dirpyrDenoise.smethod == other.dirpyrDenoise.smethod
&& dirpyrDenoise.medmethod == other.dirpyrDenoise.medmethod
&& dirpyrDenoise.methodmed == other.dirpyrDenoise.methodmed
&& dirpyrDenoise.rgbmethod == other.dirpyrDenoise.rgbmethod
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 6c376bfd0..f6ee5186a 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -32,6 +32,7 @@ namespace rtengine {
class ColorGradientCurve;
class OpacityCurve;
+class NoisCurve;
namespace procparams {
@@ -541,6 +542,8 @@ class ImpulseDenoiseParams {
class DirPyrDenoiseParams {
public:
+ std::vector lcurve;
+
bool enabled;
bool enhance;
bool median;
@@ -553,10 +556,18 @@ class DirPyrDenoiseParams {
double bluechro;
double gamma;
Glib::ustring dmethod;
+ Glib::ustring smethod;
Glib::ustring medmethod;
Glib::ustring methodmed;
Glib::ustring rgbmethod;
int passes;
+
+ DirPyrDenoiseParams ();
+ void setDefault(); // SHOULD BE GENERALIZED TO ALL CLASSES!
+ void getCurves(NoisCurve &lcurveLUT, bool &lldenoiseutili) const;
+
+ static void getDefaultNoisCurve(std::vector &curve);
+
};
//EPD related parameters.
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index f58f907af..6104e3d97 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -2081,8 +2081,8 @@ lab2ProphotoRgbD50(float L, float A, float B, float& r, float& g, float& b)
// Converts raw image including ICC input profile to working space - floating point version
void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParams &cmp, ColorTemp &wb, double pre_mul[3], const RAWParams &raw, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], const std::string &camName) {
- //MyTime t1, t2, t3;
- //t1.set ();
+ MyTime t1, t2, t3;
+ t1.set ();
cmsHPROFILE in;
DCPProfile *dcpProf;
@@ -2397,8 +2397,8 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam
cmsDeleteTransform(hTransform);
}
-//t3.set ();
-// printf ("ICM TIME: %d\n", t3.etime(t1));
+t3.set ();
+ printf ("ICM TIME: %d usec\n", t3.etime(t1));
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index 0ab3e989c..8d1ac69e7 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -317,6 +317,8 @@ DARKFRAME, // EvPreProcessExpBlackBlue
RGBCURVE, //EvFilmSimulationEnabled
RGBCURVE, //EvFilmSimulationStrength
RGBCURVE, //EvFilmSimulationFilename
+ALLNORAW, // EvDPDNLCurve
+ALLNORAW // EvDPDNsmet
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 2a97351fc..0324bcd50 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -44,6 +44,7 @@
extern Options options;
namespace rtengine {
+using namespace procparams;
Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq) {
@@ -834,6 +835,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
ToneCurve customToneCurve1, customToneCurve2;
ColorGradientCurve ctColorCurve;
OpacityCurve ctOpacityCurve;
+ // NoisCurve dnNoisCurve;
+
ColorAppearance customColCurve1;
ColorAppearance customColCurve2;
ColorAppearance customColCurve3;
@@ -864,6 +867,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
{wiprof[2][0],wiprof[2][1],wiprof[2][2]}
};
params.colorToning.getCurves(ctColorCurve, ctOpacityCurve, wp, wip);
+ //params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoisutili);
LabImage* labView = new LabImage (fw,fh);
CieImage* cieView = new CieImage (fw,fh);
@@ -884,6 +888,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
customToneCurve2.Reset();
ctColorCurve.Reset();
ctOpacityCurve.Reset();
+ // dnNoisCurve.Reset();
customToneCurvebw1.Reset();
customToneCurvebw2.Reset();
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 84ef35e62..03412108a 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -128,13 +128,26 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
imgsrc->getImage (currWB, tr, baseImg, pp, params.toneCurve, params.icm, params.raw);
if (pl) pl->setProgress (0.45);
+ LUTf Noisecurve (65536,0);
// perform luma/chroma denoise
-// CieImage *cieView;
-
+// CieImage *cieView;
+ NoisCurve dnNoisCurve;
+ bool lldenoiseutili=false;
+ Imagefloat *calclum ;
+ params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoiseutili);
+ if (params.dirpyrDenoise.enabled && lldenoiseutili) {
+ calclum = new Imagefloat (fw, fh);//for luminance denoise curve
+ if(baseImg != calclum)
+ memcpy(calclum->data,baseImg->data,baseImg->width*baseImg->height*3*sizeof(float));
+ imgsrc->convertColorSpace(calclum, params.icm, currWB, params.raw);
+ }
if (params.dirpyrDenoise.enabled) {
- ipf.RGB_denoise(baseImg, baseImg, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp());
- }
+ // CurveFactory::denoiseLL(lldenoiseutili, params.dirpyrDenoise.lcurve, Noisecurve,1);
+ //params.dirpyrDenoise.getCurves(dnNoisCurve);
+ ipf.RGB_denoise(baseImg, baseImg, calclum, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve, lldenoiseutili);
+ }
+ // delete calclum;
imgsrc->convertColorSpace(baseImg, params.icm, currWB, params.raw);
// perform first analysis
@@ -250,6 +263,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
customToneCurve2.Reset();
ctColorCurve.Reset();
ctOpacityCurve.Reset();
+ dnNoisCurve.Reset();
customToneCurvebw1.Reset();
customToneCurvebw2.Reset();
diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc
index 615f3c3e2..b8dca5ef4 100644
--- a/rtgui/dirpyrdenoise.cc
+++ b/rtgui/dirpyrdenoise.cc
@@ -19,11 +19,13 @@
#include "dirpyrdenoise.h"
#include
#include
+#include "edit.h"
using namespace rtengine;
using namespace rtengine::procparams;
DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) {
+ std::vector milestones;
enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED")));
enabled->set_tooltip_text (M("TP_DIRPYRDENOISE_ENABLED_TOOLTIP"));
@@ -44,6 +46,19 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) {
chroma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_CHROMA"), 0, 100, 0.01, 15));
redchro = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_RED"), -100, 100, 0.1, 0));
bluechro = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_BLUE"), -100, 100, 0.1, 0));
+ std::vector defaultCurve;
+
+ NoiscurveEditorG = new CurveEditorGroup (options.lastDenoiseCurvesDir, M("TP_DIRPYRDENOISE_LCURVE"));
+ //curveEditorG = new CurveEditorGroup (options.lastLabCurvesDir);
+ NoiscurveEditorG->setCurveListener (this);
+ rtengine::DirPyrDenoiseParams::getDefaultNoisCurve(defaultCurve);
+ lshape = static_cast(NoiscurveEditorG->addCurve(CT_Flat, "", NULL, false));
+ lshape->setIdentityValue(0.);
+ lshape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve);
+
+ lshape->setTooltip(M("TP_DIRPYRDENOISE_CURVEEDITOR_L_TOOLTIP"));
+ //lshape->setEditID(EUID_Lab_LCurve, BT_SINGLEPLANE_FLOAT);
+
gamma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_GAMMA"), 1.0, 3.0, 0.01, 1.7));
gamma->set_tooltip_text (M("TP_DIRPYRDENOISE_GAMMA_TOOLTIP"));
@@ -77,17 +92,17 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) {
bluechro->setAdjusterListener (this);
gamma->setAdjusterListener (this);
- passes->setAdjusterListener (this);
luma->show();
Ldetail->show();
+
+
chroma->show();
redchro->show();
bluechro->show();
// perform->show();
gamma->show();
// perform->set_active (true);
- passes->show();
enhance = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_ENH")));
enhance->set_active (false);
@@ -102,7 +117,6 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) {
hsep2->show ();
methodmed = Gtk::manage (new MyComboBoxText ());
- //methodmed->append_text (M("TP_DIRPYRDENOISE_NONE"));
methodmed->append_text (M("TP_DIRPYRDENOISE_LM"));
methodmed->append_text (M("TP_DIRPYRDENOISE_LABM"));
methodmed->append_text (M("TP_DIRPYRDENOISE_RGBM"));
@@ -131,24 +145,60 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) {
ctboxm = Gtk::manage (new Gtk::HBox ());
Gtk::Label* labmm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDMETHOD")));
- ctboxm->pack_start (*labmm, Gtk::PACK_SHRINK, 4);
+ ctboxm->pack_start (*labmm, Gtk::PACK_SHRINK, 1);
ctbox = Gtk::manage (new Gtk::HBox ());
Gtk::Label* labm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDTYPE")));
- ctbox->pack_start (*labm, Gtk::PACK_SHRINK, 4);
+ ctbox->pack_start (*labm, Gtk::PACK_SHRINK, 1);
ctboxrgb = Gtk::manage (new Gtk::HBox ());
Gtk::Label* labrgb = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDTYPE")));
- ctboxrgb->pack_start (*labrgb, Gtk::PACK_SHRINK, 4);
+ ctboxrgb->pack_start (*labrgb, Gtk::PACK_SHRINK, 1);
+
+
+ milestones.push_back( GradientMilestone(0., 0., 0., 0.) );
+ milestones.push_back( GradientMilestone(1., 1., 1., 1.) );
+ lshape->setBottomBarBgGradient(milestones);
+ //lshape->setLeftBarBgGradient(milestones);
+ milestones.push_back( GradientMilestone(0., 0., 0., 0.) );
+ milestones.push_back( GradientMilestone(1., 1., 1., 1.) );
+ NoiscurveEditorG->curveListComplete();
+
+ Gtk::HSeparator *hsep4 = Gtk::manage (new Gtk::HSeparator());
+ hsep4->show ();
+
+ Gtk::HBox* hb11 = Gtk::manage (new Gtk::HBox ());
+ hb11->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_METHOD11") +": ")),Gtk::PACK_SHRINK, 4);
+ hb11->set_tooltip_markup (M("TP_DIRPYRDENOISE_METHOD11_TOOLTIP"));
+
+ smethod = Gtk::manage (new MyComboBoxText ());
+ smethod->append_text (M("TP_DIRPYRDENOISE_SHAL"));
+// smethod->append_text (M("TP_DIRPYRDENOISE_SHBI"));
+ smethod->append_text (M("TP_DIRPYRDENOISE_SHALBI"));
+// smethod->append_text (M("TP_DIRPYRDENOISE_SHALAL"));
+// smethod->append_text (M("TP_DIRPYRDENOISE_SHBIBI"));
+ smethod->set_active(1);
+ hb11->pack_start (*smethod, Gtk::PACK_EXPAND_WIDGET, 4);
+// pack_start( *hb11, Gtk::PACK_SHRINK, 4);
+ smethodconn = smethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::smethodChanged) );
+
+ passes = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_PASSE"), 1.0, 3.0, 1., 1.));
+ passes->set_tooltip_text (M("TP_DIRPYRDENOISE_PASSES_TOOLTIP"));
+ passes->setAdjusterListener (this);
+ passes->show();
pack_start (*luma);
+ pack_start (*NoiscurveEditorG, Gtk::PACK_SHRINK, 4);
pack_start (*Ldetail);
pack_start (*chroma);
pack_start (*redchro);
pack_start (*bluechro);
pack_start (*gamma);
- pack_start (*enhance);
+ //pack_start (*enhance);
+ pack_start (*hsep4);
+
+ pack_start( *hb11, Gtk::PACK_SHRINK, 4);
pack_start (*hsep2);
pack_start (*median);
@@ -159,7 +209,8 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) {
pack_start (*ctboxm);
pack_start (*ctbox);
pack_start (*ctboxrgb);
- pack_start (*passes);
+ pack_start (*passes,Gtk::PACK_SHRINK, 1);
+
// pack_start (*perform);
@@ -168,10 +219,17 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) {
ctboxrgb->hide();
}
+DirPyrDenoise::~DirPyrDenoise () {
+ delete NoiscurveEditorG;
+}
+
+
+
void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) {
disableListener ();
dmethodconn.block(true);
+ smethodconn.block(true);
enaConn.block (true);
medmethodconn.block(true);
rgbmethodconn.block(true);
@@ -183,6 +241,19 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) {
else if (pp->dirpyrDenoise.dmethod=="Lab")
dmethod->set_active (1);
+
+ smethod->set_active (0);
+ if (pp->dirpyrDenoise.smethod=="shal")
+ smethod->set_active (0);
+// else if (pp->dirpyrDenoise.smethod=="shbi")
+// smethod->set_active (1);
+ else if (pp->dirpyrDenoise.smethod=="shalbi")
+ smethod->set_active (1);
+ // else if (pp->dirpyrDenoise.smethod=="shalal")
+ // smethod->set_active (3);
+ // else if (pp->dirpyrDenoise.smethod=="shbibi")
+ // smethod->set_active (4);
+
methodmed->set_active (0);
// if (pp->dirpyrDenoise.methodmed=="none")
// methodmed->set_active (0);
@@ -224,6 +295,8 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) {
if (pedited) {
if (!pedited->dirpyrDenoise.dmethod)
dmethod->set_active (2);
+ if (!pedited->dirpyrDenoise.smethod)
+ smethod->set_active (2);
if (!pedited->dirpyrDenoise.rgbmethod)
rgbmethod->set_active (2);
if (!pedited->dirpyrDenoise.medmethod)
@@ -263,16 +336,24 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) {
gamma->setValue (pp->dirpyrDenoise.gamma);
passes->setValue (pp->dirpyrDenoise.passes);
+ lshape->setCurve (pp->dirpyrDenoise.lcurve);
enaConn.block (false);
dmethodconn.block(false);
+ smethodconn.block(false);
medmethodconn.block(false);
rgbmethodconn.block(false);
methodmedconn.block(false);
enableListener ();
}
-
+void DirPyrDenoise::setEditProvider (EditDataProvider *provider) {
+ lshape->setEditProvider(provider);
+}
+void DirPyrDenoise::autoOpenCurve () {
+ // Open up the first curve if selected
+ bool active = lshape->openIfNonlinear();
+}
void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) {
pp->dirpyrDenoise.luma = luma->getValue ();
@@ -286,9 +367,11 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) {
pp->dirpyrDenoise.enhance = enhance->get_active();
// pp->dirpyrDenoise.perform = perform->get_active();
pp->dirpyrDenoise.median = median->get_active();
+ pp->dirpyrDenoise.lcurve = lshape->getCurve ();
if (pedited) {
pedited->dirpyrDenoise.dmethod = dmethod->get_active_row_number() != 2;
+ pedited->dirpyrDenoise.smethod = smethod->get_active_row_number() != 2;
pedited->dirpyrDenoise.medmethod = medmethod->get_active_row_number() != 4;
pedited->dirpyrDenoise.rgbmethod = rgbmethod->get_active_row_number() != 2;
pedited->dirpyrDenoise.methodmed = methodmed->get_active_row_number() != 2;
@@ -302,6 +385,8 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) {
pedited->dirpyrDenoise.enabled = !enabled->get_inconsistent();
pedited->dirpyrDenoise.enhance = !enhance->get_inconsistent();
pedited->dirpyrDenoise.median = !median->get_inconsistent();
+ pedited->dirpyrDenoise.lcurve = !lshape->isUnChanged ();
+
// pedited->dirpyrDenoise.perform = !perform->get_inconsistent();
}
if (dmethod->get_active_row_number()==0)
@@ -309,6 +394,17 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) {
else if (dmethod->get_active_row_number()==1)
pp->dirpyrDenoise.dmethod = "Lab";
+ if (smethod->get_active_row_number()==0)
+ pp->dirpyrDenoise.smethod = "shal";
+ // else if (smethod->get_active_row_number()==1)
+// pp->dirpyrDenoise.smethod = "shbi";
+ else if (smethod->get_active_row_number()==1)
+ pp->dirpyrDenoise.smethod = "shalbi";
+// else if (smethod->get_active_row_number()==3)
+// pp->dirpyrDenoise.smethod = "shalal";
+// else if (smethod->get_active_row_number()==4)
+// pp->dirpyrDenoise.smethod = "shbibi";
+
// if (methodmed->get_active_row_number()==0)
// pp->dirpyrDenoise.methodmed = "none";
if (methodmed->get_active_row_number()==0)
@@ -342,6 +438,13 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) {
}
+void DirPyrDenoise::curveChanged () {
+
+ if (listener && enabled->get_active()) {
+ listener->panelChanged (EvDPDNLCurve, M("HISTORY_CUSTOMCURVE"));
+ }
+}
+
void DirPyrDenoise::dmethodChanged () {
if (listener && (multiImage||enabled->get_active()) ) {
@@ -349,6 +452,13 @@ void DirPyrDenoise::dmethodChanged () {
}
}
+void DirPyrDenoise::smethodChanged () {
+
+ if (listener && (multiImage||enabled->get_active()) ) {
+ listener->panelChanged (EvDPDNsmet, smethod->get_active_text ());
+ }
+}
+
void DirPyrDenoise::medmethodChanged () {
@@ -539,7 +649,10 @@ void DirPyrDenoise::setBatchMode (bool batchMode) {
bluechro->showEditedCB ();
gamma->showEditedCB ();
passes->showEditedCB ();
+ NoiscurveEditorG->setBatchMode (batchMode);
+
dmethod->append_text (M("GENERAL_UNCHANGED"));
+ smethod->append_text (M("GENERAL_UNCHANGED"));
medmethod->append_text (M("GENERAL_UNCHANGED"));
methodmed->append_text (M("GENERAL_UNCHANGED"));
rgbmethod->append_text (M("GENERAL_UNCHANGED"));
diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h
index 88d5e88ed..d40760b87 100644
--- a/rtgui/dirpyrdenoise.h
+++ b/rtgui/dirpyrdenoise.h
@@ -22,10 +22,15 @@
#include
#include "adjuster.h"
#include "toolpanel.h"
+#include "curveeditor.h"
+#include "curveeditorgroup.h"
+#include "colorprovider.h"
+#include "guiutils.h"
-class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel {
+class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider {
protected:
+ CurveEditorGroup* NoiscurveEditorG;
Adjuster* luma;
Adjuster* Ldetail;
Adjuster* chroma;
@@ -33,6 +38,7 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol
Adjuster* bluechro;
Adjuster* gamma;
Adjuster* passes;
+ FlatCurveEditor* lshape;
Gtk::CheckButton* enabled;
bool lastEnabled;
@@ -48,6 +54,8 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol
// sigc::connection perfconn;
MyComboBoxText* dmethod;
sigc::connection dmethodconn;
+ MyComboBoxText* smethod;
+ sigc::connection smethodconn;
MyComboBoxText* medmethod;
sigc::connection medmethodconn;
Gtk::HBox* ctbox;
@@ -62,11 +70,15 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol
public:
DirPyrDenoise ();
+ ~DirPyrDenoise ();
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
void setBatchMode (bool batchMode);
+ void curveChanged ();
+ void setEditProvider (EditDataProvider *provider);
+ void autoOpenCurve ();
void adjusterChanged (Adjuster* a, double newval);
void enabledChanged ();
@@ -77,6 +89,7 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol
void medmethodChanged ();
void methodmedChanged ();
void rgbmethodChanged ();
+ void smethodChanged ();
void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd);
void trimValues (rtengine::procparams::ProcParams* pp);
diff --git a/rtgui/options.cc b/rtgui/options.cc
index 4e9962e26..828cfafac 100644
--- a/rtgui/options.cc
+++ b/rtgui/options.cc
@@ -146,6 +146,8 @@ void Options::updatePaths() {
lastRgbCurvesDir = preferredPath;
if (lastLabCurvesDir.empty() || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR))
lastLabCurvesDir = preferredPath;
+ if (lastDenoiseCurvesDir.empty() || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_IS_DIR))
+ lastDenoiseCurvesDir = preferredPath;
if (lastPFCurvesDir.empty() || !safe_file_test (lastPFCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastPFCurvesDir, Glib::FILE_TEST_IS_DIR))
lastPFCurvesDir = preferredPath;
if (lastHsvCurvesDir.empty() || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_IS_DIR))
@@ -554,6 +556,7 @@ void Options::setDefaults () {
// at the end of the "updatePaths" method.
lastRgbCurvesDir = "";
lastLabCurvesDir = "";
+ lastDenoiseCurvesDir = "";
lastPFCurvesDir = "";
lastHsvCurvesDir = "";
lastToneCurvesDir = "";
@@ -859,6 +862,7 @@ if (keyFile.has_group ("Dialogs")) {
safeDirGet(keyFile, "Dialogs", "LastFlatfieldDir", lastFlatfieldDir);
safeDirGet(keyFile, "Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir);
safeDirGet(keyFile, "Dialogs", "LastLabCurvesDir", lastLabCurvesDir);
+ safeDirGet(keyFile, "Dialogs", "LastDenoiseCurvesDir", lastDenoiseCurvesDir);
safeDirGet(keyFile, "Dialogs", "LastPFCurvesDir", lastPFCurvesDir);
safeDirGet(keyFile, "Dialogs", "LastHsvCurvesDir", lastHsvCurvesDir);
safeDirGet(keyFile, "Dialogs", "LastBWCurvesDir", lastBWCurvesDir);
@@ -1147,6 +1151,7 @@ int Options::saveToFile (Glib::ustring fname) {
keyFile.set_string ("Dialogs", "LastFlatfieldDir", lastFlatfieldDir);
keyFile.set_string ("Dialogs", "LastRgbCurvesDir", lastRgbCurvesDir);
keyFile.set_string ("Dialogs", "LastLabCurvesDir", lastLabCurvesDir);
+ keyFile.set_string ("Dialogs", "LastDenoiseCurvesDir", lastDenoiseCurvesDir);
keyFile.set_string ("Dialogs", "LastPFCurvesDir", lastPFCurvesDir);
keyFile.set_string ("Dialogs", "LastHsvCurvesDir", lastHsvCurvesDir);
keyFile.set_string ("Dialogs", "LastBWCurvesDir", lastBWCurvesDir);
diff --git a/rtgui/options.h b/rtgui/options.h
index c552b1e74..8b7c305ff 100644
--- a/rtgui/options.h
+++ b/rtgui/options.h
@@ -112,11 +112,11 @@ class Options {
int historyPanelWidth;
Glib::ustring font;
int windowWidth;
- int windowHeight;
- int windowX;
+ int windowHeight;
+ int windowX;
int windowY;
- bool windowMaximized;
- int detailWindowWidth;
+ bool windowMaximized;
+ int detailWindowWidth;
int detailWindowHeight;
int dirBrowserWidth;
int dirBrowserHeight;
@@ -263,6 +263,7 @@ class Options {
Glib::ustring lastFlatfieldDir;
Glib::ustring lastRgbCurvesDir;
Glib::ustring lastLabCurvesDir;
+ Glib::ustring lastDenoiseCurvesDir;
Glib::ustring lastPFCurvesDir;
Glib::ustring lastHsvCurvesDir;
Glib::ustring lastToneCurvesDir;
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 07b0722fa..2c60b6da2 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -181,6 +181,7 @@ void ParamsEdited::set (bool v) {
dirpyrDenoise.enabled = v;
dirpyrDenoise.enhance = v;
// dirpyrDenoise.perform = v;
+ dirpyrDenoise.lcurve = v;
dirpyrDenoise.median = v;
dirpyrDenoise.luma = v;
dirpyrDenoise.Ldetail = v;
@@ -190,6 +191,7 @@ void ParamsEdited::set (bool v) {
dirpyrDenoise.gamma = v;
dirpyrDenoise.passes = v;
dirpyrDenoise.dmethod = v;
+ dirpyrDenoise.smethod = v;
dirpyrDenoise.medmethod = v;
dirpyrDenoise.methodmed = v;
dirpyrDenoise.rgbmethod = v;
@@ -512,6 +514,7 @@ void ParamsEdited::initFrom (const std::vector
dirpyrDenoise.median = dirpyrDenoise.median && p.dirpyrDenoise.median == other.dirpyrDenoise.median;
// dirpyrDenoise.perform = dirpyrDenoise.perform && p.dirpyrDenoise.perform == other.dirpyrDenoise.perform;
dirpyrDenoise.luma = dirpyrDenoise.luma && p.dirpyrDenoise.luma == other.dirpyrDenoise.luma;
+ dirpyrDenoise.lcurve = dirpyrDenoise.lcurve && p.dirpyrDenoise.lcurve == other.dirpyrDenoise.lcurve;
dirpyrDenoise.Ldetail = dirpyrDenoise.Ldetail && p.dirpyrDenoise.Ldetail == other.dirpyrDenoise.Ldetail;
dirpyrDenoise.chroma = dirpyrDenoise.chroma && p.dirpyrDenoise.chroma == other.dirpyrDenoise.chroma;
dirpyrDenoise.redchro = dirpyrDenoise.redchro && p.dirpyrDenoise.redchro == other.dirpyrDenoise.redchro;
@@ -519,6 +522,7 @@ void ParamsEdited::initFrom (const std::vector
dirpyrDenoise.gamma = dirpyrDenoise.gamma && p.dirpyrDenoise.gamma == other.dirpyrDenoise.gamma;
dirpyrDenoise.passes = dirpyrDenoise.passes && p.dirpyrDenoise.passes == other.dirpyrDenoise.passes;
dirpyrDenoise.dmethod = dirpyrDenoise.dmethod && p.dirpyrDenoise.dmethod == other.dirpyrDenoise.dmethod;
+ dirpyrDenoise.smethod = dirpyrDenoise.smethod && p.dirpyrDenoise.smethod == other.dirpyrDenoise.smethod;
dirpyrDenoise.medmethod = dirpyrDenoise.medmethod && p.dirpyrDenoise.medmethod == other.dirpyrDenoise.medmethod;
dirpyrDenoise.methodmed = dirpyrDenoise.methodmed && p.dirpyrDenoise.methodmed == other.dirpyrDenoise.methodmed;
dirpyrDenoise.rgbmethod = dirpyrDenoise.rgbmethod && p.dirpyrDenoise.rgbmethod == other.dirpyrDenoise.rgbmethod;
@@ -844,6 +848,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (dirpyrDenoise.enhance) toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance;
if (dirpyrDenoise.median) toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median;
if (dirpyrDenoise.luma) toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma;
+ if (dirpyrDenoise.lcurve) toEdit.dirpyrDenoise.lcurve = mods.dirpyrDenoise.lcurve;
if (dirpyrDenoise.Ldetail) toEdit.dirpyrDenoise.Ldetail = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMDET] ? toEdit.dirpyrDenoise.Ldetail + mods.dirpyrDenoise.Ldetail : mods.dirpyrDenoise.Ldetail;
if (dirpyrDenoise.chroma) toEdit.dirpyrDenoise.chroma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMA] ? toEdit.dirpyrDenoise.chroma + mods.dirpyrDenoise.chroma : mods.dirpyrDenoise.chroma;
if (dirpyrDenoise.redchro) toEdit.dirpyrDenoise.redchro = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMARED] ? toEdit.dirpyrDenoise.redchro + mods.dirpyrDenoise.redchro : mods.dirpyrDenoise.redchro;
@@ -852,6 +857,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (dirpyrDenoise.passes) toEdit.dirpyrDenoise.passes = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_PASSES] ? toEdit.dirpyrDenoise.passes + mods.dirpyrDenoise.passes : mods.dirpyrDenoise.passes;
// if (dirpyrDenoise.perform) toEdit.dirpyrDenoise.perform = mods.dirpyrDenoise.perform;
if (dirpyrDenoise.dmethod) toEdit.dirpyrDenoise.dmethod = mods.dirpyrDenoise.dmethod;
+ if (dirpyrDenoise.smethod) toEdit.dirpyrDenoise.smethod = mods.dirpyrDenoise.smethod;
if (dirpyrDenoise.medmethod) toEdit.dirpyrDenoise.medmethod = mods.dirpyrDenoise.medmethod;
if (dirpyrDenoise.methodmed) toEdit.dirpyrDenoise.methodmed = mods.dirpyrDenoise.methodmed;
if (dirpyrDenoise.rgbmethod) toEdit.dirpyrDenoise.rgbmethod = mods.dirpyrDenoise.rgbmethod;
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index b86fce969..e2fbe40de 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -272,8 +272,11 @@ public:
bool redchro;
bool bluechro;
bool gamma;
+ bool lcurve;
+
// bool perform;
bool dmethod;
+ bool smethod;
bool medmethod;
bool methodmed;
bool rgbmethod;