From 5d6d858aac930b1a00f27eadf56eb1a6f4465753 Mon Sep 17 00:00:00 2001 From: jdc Date: Sat, 30 Aug 2014 07:10:26 +0200 Subject: [PATCH] Luminance Denoise Curve issue2463 --- rtdata/languages/default | 10 + rtengine/FTblockDN.cc | 376 +++++++++++++++++++++++++++------- rtengine/curves.cc | 59 ++++++ rtengine/curves.h | 13 ++ rtengine/dcrop.cc | 25 ++- rtengine/improccoordinator.cc | 30 ++- rtengine/improccoordinator.h | 4 +- rtengine/improcfun.h | 8 +- rtengine/procevents.h | 3 + rtengine/procparams.cc | 58 +++++- rtengine/procparams.h | 11 + rtengine/rawimagesource.cc | 8 +- rtengine/refreshmap.cc | 2 + rtengine/rtthumbnail.cc | 5 + rtengine/simpleprocess.cc | 22 +- rtgui/dirpyrdenoise.cc | 131 +++++++++++- rtgui/dirpyrdenoise.h | 15 +- rtgui/options.cc | 5 + rtgui/options.h | 9 +- rtgui/paramsedited.cc | 6 + rtgui/paramsedited.h | 3 + 21 files changed, 690 insertions(+), 113 deletions(-) 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;