From 47ed53084d4ce2b231b474be2d285cc7d8e03233 Mon Sep 17 00:00:00 2001 From: jdc Date: Wed, 5 Nov 2014 15:04:18 +0100 Subject: [PATCH] Noise Reduction - auto chroma issue2495 --- rtdata/languages/default | 66 +- rtengine/FTblockDN.cc | 1437 +++++++++++++++++++++++++++++---- rtengine/curves.cc | 50 +- rtengine/curves.h | 15 +- rtengine/dcrop.cc | 463 ++++++++++- rtengine/improccoordinator.cc | 47 +- rtengine/improccoordinator.h | 6 + rtengine/improcfun.h | 42 +- rtengine/procevents.h | 5 + rtengine/procparams.cc | 45 +- rtengine/procparams.h | 10 +- rtengine/refreshmap.cc | 7 +- rtengine/rtengine.h | 12 + rtengine/settings.h | 10 + rtengine/simpleprocess.cc | 427 +++++++++- rtgui/cropwindow.cc | 2 +- rtgui/dirpyrdenoise.cc | 699 ++++++++++++++-- rtgui/dirpyrdenoise.h | 53 +- rtgui/editorpanel.cc | 86 +- rtgui/editorpanel.h | 1 + rtgui/options.cc | 31 + rtgui/paramsedited.cc | 17 +- rtgui/paramsedited.h | 5 + rtgui/preferences.cc | 100 ++- rtgui/preferences.h | 6 + rtgui/toolpanelcoord.cc | 1 + 26 files changed, 3302 insertions(+), 341 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index b6b422fbe..8c77b4e90 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -514,6 +514,11 @@ HISTORY_MSG_295;Film Simulation - Film HISTORY_MSG_296;NR - Modulate luminance HISTORY_MSG_297;NR - Quality HISTORY_MSG_298;Dead pixel filter +HISTORY_MSG_299;NR - Chrominance curve +HISTORY_MSG_300;- +HISTORY_MSG_301;NR - Luma control +HISTORY_MSG_302;NR - Chroma method +HISTORY_MSG_303;- HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOTS;Snapshots @@ -741,6 +746,30 @@ PREFERENCES_D50;5000K PREFERENCES_D55;5500K PREFERENCES_D60;6000K PREFERENCES_D65;6500K +PREFERENCES_LEVDN;Cell size +PREFERENCES_MIN;Mini (100x115) +PREFERENCES_SMA;Small (250x287) +PREFERENCES_MED;Medium (Tile/2) +PREFERENCES_MAX;Maxi (Tile) +PREFERENCES_NOISE;Noise Reduction +PREFERENCES_LEVAUTDN;Denoising level +PREFERENCES_AUTLOW;Low +PREFERENCES_AUTSTD;Standard +PREFERENCES_SIMPLAUT;Tool mode +PREFERENCES_STDAUT;Standard +PREFERENCES_EXPAUT;Expert +PREFERENCES_LISS;Auto multi-zone smoothing +PREFERENCES_AUTLISVLOW;None +PREFERENCES_AUTLISLOW;Low +PREFERENCES_AUTLISSTD;High +PREFERENCES_AUTLISMAX;Max - Average of all tiles +PREFERENCES_TINB;Number of tiles +PREFERENCES_TISTD;Standard +PREFERENCES_TIMAX;High +PREFERENCES_WAVLEV;Increase wavelet level in quality 'high' +PREFERENCES_WLZER;No +PREFERENCES_WLONE;One level +PREFERENCES_WLTWO;Two levels PREFERENCES_DARKFRAMEFOUND;Found PREFERENCES_DARKFRAMESHOTS;shots PREFERENCES_DARKFRAMETEMPLATES;templates @@ -832,7 +861,7 @@ PREFERENCES_PROFILESAVECACHE;Save processing profile to the cache PREFERENCES_PROFILESAVEINPUT;Save processing profile next to the input file PREFERENCES_PROPERTY;Property PREFERENCES_PSPATH;Adobe Photoshop installation directory -PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction +PREFERENCES_RGBDTL_LABEL;Max number of threads PREFERENCES_RGBDTL_TOOLTIP;Noise Reduction requires a baseline of about 128MB RAM for a 10MPix image or 512MB for a 40MPix image, and additionally 128MB RAM per thread. The more threads run in parallel, the faster the computation. Leave the setting at "0" to automatically use as many threads as possible. PREFERENCES_SELECTFONT;Select font PREFERENCES_SELECTLANG;Select language @@ -855,7 +884,7 @@ PREFERENCES_TAB_BROWSER;File Browser PREFERENCES_TAB_COLORMGR;Color Management PREFERENCES_TAB_GENERAL;General PREFERENCES_TAB_IMPROC;Image Processing -PREFERENCES_TAB_PERFORMANCE;Performance +PREFERENCES_TAB_PERFORMANCE;Performance & Quality PREFERENCES_TAB_SOUND;Sounds PREFERENCES_TP_LABEL;Tool panel: PREFERENCES_TP_USEICONORTEXT;Use tab icons instead of text @@ -1140,6 +1169,7 @@ TP_DIRPYRDENOISE_33;3×3 strong TP_DIRPYRDENOISE_55SOFT;5×5 TP_DIRPYRDENOISE_55;5×5 strong TP_DIRPYRDENOISE_77;7×7 (slow) +TP_DIRPYRDENOISE_99;9x9 (very slow) TP_DIRPYRDENOISE_BLUE;Chrominance - Blue-Yellow TP_DIRPYRDENOISE_CHROMA;Chrominance - Master TP_DIRPYRDENOISE_CURVEEDITOR_L_TOOLTIP;Modulates action of 'Luminance' denoise @@ -1151,20 +1181,48 @@ TP_DIRPYRDENOISE_GAMMA_TOOLTIP;Gamma varies noise reduction strength across the TP_DIRPYRDENOISE_LABEL;Noise Reduction TP_DIRPYRDENOISE_LABM;L*a*b* TP_DIRPYRDENOISE_LAB;L*a*b* +TP_DIRPYRDENOISE_ABM;Chroma only +TP_DIRPYRDENOISE_LPLABM;Weighted L* (little) + a*b* (normal) +TP_DIRPYRDENOISE_LTYPE;Luminance type TP_DIRPYRDENOISE_LCURVE;Luminance curve +TP_DIRPYRDENOISE_SLI;Slider +TP_DIRPYRDENOISE_CUR;Curve +TP_DIRPYRDENOISE_LUMAFR;Luminance +TP_DIRPYRDENOISE_LUMAFR_TOOLTIP;Wavelet on luminance and Fourier transform for luminance detail +TP_DIRPYRDENOISE_CHROMAFR;Chrominance +TP_DIRPYRDENOISE_AUTO;Auto chroma +TP_DIRPYRDENOISE_CTYPE;Auto method +TP_DIRPYRDENOISE_CTYPE_TOOLTIP;Manual\nActs on the full image.\nYou control the noise reduction settings manually.\n\nAutomatic global\nActs on the full image.\n9 zones are used to calculate a global chrominance noise reduction setting.\n\nAutomatic multi-zones\nNo preview - works only during saving, but using the "Preview" method by matching the tile size and center to the preview size and center you can get an idea of the expected results.\nThe image is divided into tiles (about 10 to 70 depending on image size) and each tile receives its own chrominance noise reduction settings.\n\nPreview\nActs on the whole image.\nThe part of the image visible in the preview is used to calculate global chrominance noise reduction settings. +TP_DIRPYRDENOISE_C2TYPE_TOOLTIP;Manual\nActs on the full image.\nYou control the noise reduction settings manually.\n\nAutomatic global\nActs on the full image.\n9 zones are used to calculate a global chrominance noise reduction setting.\n\nPreview\nActs on the whole image.\nThe part of the image visible in the preview is used to calculate global chrominance noise reduction settings. +TP_DIRPYRDENOISE_MAN;Manual +TP_DIRPYRDENOISE_MANU;Manual +TP_DIRPYRDENOISE_AUT;Automatic global +TP_DIRPYRDENOISE_AUTO;Automatic global +TP_DIRPYRDENOISE_PON;Auto multi-zones +TP_DIRPYRDENOISE_PRE;Preview multi-zones +TP_DIRPYRDENOISE_PREV;Preview +TP_DIRPYRDENOISE_AUTO_TOOLTIP;Try to evaluate chroma noise\nBe careful, this calculation is average, and is quite subjective ! +TP_DIRPYRDENOISE_NOISELABEL;Preview noise: Mean=%1 High=%2 +TP_DIRPYRDENOISE_TILELABEL;Tile size=%1, Center: Tx=%2 Ty=%3 +TP_DIRPYRDENOISE_PREVLABEL;Preview size=%1, Center: Px=%2 Py=%3 +TP_DIRPYRDENOISE_NOISELABELEMPTY;Preview noise: Mean= - High= - +TP_DIRPYRDENOISE_NRESID_TOOLTIP;Displays the remaining noise levels of the part of the image visible in the preview after wavelet.\n\n>300 Very noisy\n100-300 Noisy\n50-100 A little noisy\n<50 Very low noise\n\nBeware, the values will differ between RGB and L*a*b* mode. The RGB values are less accurate because the RGB mode does not completely separate luminance and chrominance. +TP_DIRPYRDENOISE_CCCURVE;Chrominance curve +TP_DIRPYRDENOISE_CURVEEDITOR_CC;Chroma +TP_DIRPYRDENOISE_CURVEEDITOR_CC_TOOLTIP;Increase (multiply) the value of all chrominance sliders.\nThis curve lets you adjust the strength of chromatic noise reduction as a function of chromaticity, for instance to increase the action in areas of low saturation and to decrease it in those of high saturation. TP_DIRPYRDENOISE_LDETAIL;Luminance - Detail TP_DIRPYRDENOISE_LM;Luminance only TP_DIRPYRDENOISE_LUMA;Luminance TP_DIRPYRDENOISE_MEDMETHOD;Median method TP_DIRPYRDENOISE_MEDTYPE;Median type -TP_DIRPYRDENOISE_MED;Median +TP_DIRPYRDENOISE_MED;Median Filter TP_DIRPYRDENOISE_MED_TOOLTIP;Enabled median denoising TP_DIRPYRDENOISE_METHOD11;Quality TP_DIRPYRDENOISE_METHOD11_TOOLTIP;Quality can be adapted to the noise pattern. A setting of "high" increases the noise reduction effect at a cost of extended processing time. TP_DIRPYRDENOISE_METHOD;Method TP_DIRPYRDENOISE_METHOD_TOOLTIP;For raw images either RGB or L*a*b* methods can be used.\n\nFor non-raw images the L*a*b* method will be used, regardless of the selection. TP_DIRPYRDENOISE_METM_TOOLTIP;When using the "Luminance only" and "L*a*b*" methods, median filtering will be performed just after the wavelet step in the noise reduction pipeline.\nWhen using the "RGB" mode, it will be performed at the very end of the noise reduction pipeline. -TP_DIRPYRDENOISE_MET_TOOLTIP;Apply a median filter of the desired size. The larger the size, the longer it takes.\n\n3x3 soft: treats 5 pixels in a 1-pixel range.\n3x3: treats 9 pixels in a 1-pixel range.\n5x5 soft: treats 13 pixels in a 2-pixel range.\n5x5: treats 25 pixels in a 2-pixel range.\n7x7: treats 49 pixels in a 3-pixel range.\n\nSometimes it is possible to achieve higher quality running several iterations with a small range than one iteration with a large range. +TP_DIRPYRDENOISE_MET_TOOLTIP;Apply a median filter of the desired size. The larger the size, the longer it takes.\n\n3x3 soft: treats 5 pixels in a 1-pixel range.\n3x3: treats 9 pixels in a 1-pixel range.\n5x5 soft: treats 13 pixels in a 2-pixel range.\n5x5: treats 25 pixels in a 2-pixel range.\n7x7: treats 49 pixels in a 3-pixel range.\n9x9: treats 81 pixels in a 4-pixel range.\n\nSometimes it is possible to achieve higher quality running several iterations with a small range than one iteration with a large range. TP_DIRPYRDENOISE_PASSES;Median iterations TP_DIRPYRDENOISE_PASSES_TOOLTIP;Applying a 3x3 median filter with three iterations often leads to better results than applying 7x7 once. TP_DIRPYRDENOISE_RED;Chrominance - Red-Green diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index ed6e6ed87..d7fc862cd 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -42,6 +42,7 @@ #include "mytime.h" #include "sleef.c" #include "opthelper.h" +#include "StopWatch.h" #ifdef _OPENMP #include @@ -208,20 +209,58 @@ float media(float *elements, int N) return elements[N >> 1]; } +void ImProcFunctions::Tile_calc (int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip) - 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) +{ + if(kall==2) { + + if (imwidthheight; wid=calclum->width; TMatrix wprofi = iccStore->workingSpaceMatrix (params->icm.working); @@ -234,6 +273,12 @@ float media(float *elements, int N) lumcalc = new float*[hei]; for (int i=0; ir(ii,jj); float GL = calclum->g(ii,jj); float BL = calclum->b(ii,jj); @@ -249,12 +295,13 @@ float media(float *elements, int N) Color::rgbxyz(RL,GL,BL,XL,YL,ZL,wpi); Color::XYZ2Lab(XL, YL, ZL, LLum, AAum, BBum); lumcalc[ii][jj]=LLum; + acalc[ii][jj]=AAum; + bcalc[ii][jj]=BBum; } } delete calclum; } -// if(lldenoiseutili) printf("cest bon\n"); else printf("cest mauvais\n"); //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -268,15 +315,16 @@ float media(float *elements, int N) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% const short int imheight=src->height, imwidth=src->width; - + // printf("imW=%d imH=%d\n",imwidth,imheight); + // printf("Chroma=%f\n", dnparams.chroma); if (dnparams.luma==0 && dnparams.chroma==0 && !dnparams.median ) { //nothing to do; copy src to dst or do nothing in case src == dst if(src != dst) 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 - + Qhigh=1.0f; + if(dnparams.smethod=="shalbi") Qhigh=1.f/(float) settings->nrhigh; if (dnparams.luma!=0 || dnparams.chroma!=0 || dnparams.methodmed=="Lab" || dnparams.methodmed=="Lonly" ) { perf=false; if(dnparams.dmethod=="RGB") perf=true;//RGB mode @@ -320,8 +368,6 @@ float media(float *elements, int N) } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //srand((unsigned)time(0));//test with random data const float gain = pow (2.0f, float(expcomp)); @@ -362,31 +408,20 @@ float media(float *elements, int N) Imagefloat * dsttmp = new Imagefloat(imwidth,imheight); for (int n=0; n<3*imwidth*imheight; n++) dsttmp->data[n] = 0; - const int tilesize = 1024; - const int overlap = 128; + int tilesize; + int overlap; + if(settings->leveldnti ==0) { + tilesize = 1024; + overlap = 128; + } + if(settings->leveldnti ==1) { + tilesize = 768; + overlap = 96; + } int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; - - if (imwidthworkingSpaceMatrix (params->icm.working); double wp[3][3] = { @@ -450,9 +492,8 @@ float media(float *elements, int N) {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, {wiprof[2][0],wiprof[2][1],wiprof[2][2]} }; - - - + // int wcr,hcr; + #ifdef _OPENMP #pragma omp critical #endif @@ -466,13 +507,46 @@ float media(float *elements, int N) #ifdef _OPENMP #pragma omp for schedule(dynamic) collapse(2) #endif - for (int tiletop=0; tiletopleveldnautsimpl==1 && params->dirpyrDenoise.Cmethod=="PON") {ponder=true;ponderCC=0.5f;} + if(settings->leveldnautsimpl==1 && params->dirpyrDenoise.Cmethod=="PRE") {ponderCC=0.5f;} + if(settings->leveldnautsimpl==0 && params->dirpyrDenoise.Cmethod=="PREV") {ponderCC=0.5f;} + + float realred2, realred, realblue, realblue2; + float interm_med =(float) dnparams.chroma/10.0; + float intermred, intermblue; + if(dnparams.redchro > 0.) intermred=(dnparams.redchro/10.); else intermred= (float) dnparams.redchro/7.0;//increase slower than linear for more sensit + if(dnparams.bluechro > 0.) intermblue=(dnparams.bluechro/10.); else intermblue= (float) dnparams.bluechro/7.0;//increase slower than linear for more sensit + if(ponder && kall==2){interm_med=ch_M[pos]/10.f; intermred=max_r[pos]/10.f;intermblue=max_b[pos]/10.f;} + if(ponder && kall==0){interm_med=0.01f; intermred=0.f;intermblue=0.f;} + realred = interm_med + intermred; if (realred < 0.f) realred=0.001f; + realblue = interm_med + intermblue; if (realblue < 0.f) realblue=0.001f; + // printf("Ch=%f red=%f blu=%f\n",interm_med, intermred,intermblue ); + //input L channel array2D Lin(width,height); //wavelet denoised image @@ -483,12 +557,17 @@ float media(float *elements, int N) 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); @@ -506,20 +585,13 @@ float media(float *elements, int N) 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]; } + if(dnNoisCCcurve) { + alum=acalc[i][j]; + blum=bcalc[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 @@ -565,11 +637,29 @@ float media(float *elements, int N) 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)); + noisevarab_r = SQR(realred); + noisevarab_b = SQR(realblue); + if(dnNoisCCcurve) { + float aN=alum; + float bN=blum; + float epsic=0.01f; + float kN=Llum;//with no gamma and take into account working profile + if(kN<2.f) kN=2.f;//avoid divided by zero + if(kN>32768.f) kN=32768.f; // not strictly necessary + + float cN=sqrt(SQR(aN)+SQR(bN)); + if(cN < 100.f) cN=100.f;//avoid divided by zero + float Cinterm=1.f + ponderCC*4.f*dnNoisCCcurve.lutNoisCCcurve[(cN/30000.f)*500.f];//C=f(C) + noisevarchrom[i1][j1]= max(noisevarab_b,noisevarab_r)*SQR(Cinterm); + // printf("NC=%f ",noisevarchrom[i1][j1]); + } + + //end chroma labdn->L[i1][j1] = L; labdn->a[i1][j1] = a; labdn->b[i1][j1] = b; + Lin[i1][j1] = L; // totwt[i1][j1] = 0; } @@ -587,18 +677,14 @@ float media(float *elements, int N) 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]; } + if(dnNoisCCcurve) { + alum=acalc[i][j]; + blum=bcalc[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); @@ -616,6 +702,19 @@ float media(float *elements, int N) noisevarlum[i1][j1]= SQR((ki/125.f)*(1.f+ki/25.f)); } noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f)); + noisevarab_r = SQR(realred); + noisevarab_b = SQR(realblue); + if(dnNoisCCcurve) { + float aN=alum; + float bN=blum; + float epsic=0.01f; + + float cN=sqrt(SQR(aN)+SQR(bN)); + if(cN < 100.f) cN=100.f;//avoid divided by zero + float Cinterm=1.f + ponderCC*4.f*dnNoisCCcurve.lutNoisCCcurve[(cN/30000.f)*500.f]; + noisevarchrom[i1][j1]=max(noisevarab_b,noisevarab_r)*SQR(Cinterm); + } + //end chroma labdn->L[i1][j1] = Y; labdn->a[i1][j1] = (X-Y); @@ -650,6 +749,9 @@ float media(float *elements, int N) rtmp = rtmp<65535.0f ? gamcurve[rtmp] : (Color::gamman((double)rtmp/65535.0, gam)*32768.0f); gtmp = gtmp<65535.0f ? gamcurve[gtmp] : (Color::gamman((double)gtmp/65535.0, gam)*32768.0f); btmp = btmp<65535.0f ? gamcurve[btmp] : (Color::gamman((double)btmp/65535.0, gam)*32768.0f); + + noisevarab_r = SQR(realred); + noisevarab_b = SQR(realblue); float X,Y,Z; @@ -658,7 +760,7 @@ float media(float *elements, int N) //convert Lab Color::XYZ2Lab(X, Y, Z, L, a, b); float Llum,alum,blum; - if(dnNoisCurve) { + if(dnNoisCurve || dnNoisCCcurve) { float XL,YL,ZL; Color::rgbxyz(rLum,gLum,bLum,XL,YL,ZL,wp); Color::XYZ2Lab(XL, YL, ZL, Llum, alum, blum); @@ -680,6 +782,15 @@ float media(float *elements, int N) noisevarlum[i1][j1]=SQR((ki/125.f)*(1.f+ki/25.f)); } noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f)); + if(dnNoisCCcurve) { + float aN=alum; + float bN=blum; + float epsic=0.01f; + float cN=sqrt(SQR(aN)+SQR(bN)); + if(cN < 100.f) cN=100.f;//avoid divided by zero + float Cinterm=1.f + ponderCC*4.f*dnNoisCCcurve.lutNoisCCcurve[(cN/30000.f)*500.f]; + noisevarchrom[i1][j1]=max(noisevarab_b,noisevarab_r)*SQR(Cinterm); + } labdn->L[i1][j1] = L; labdn->a[i1][j1] = a; @@ -706,66 +817,54 @@ float media(float *elements, int N) //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))); - float interm_med= (float) dnparams.chroma/10.0; - // printf("inter=%f\n",interm_med); - float intermred, intermblue; - 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.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.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.001f; - float realblue2 = interm_med + intermblue2; if (realblue2 < 0.f) realblue2=0.001f; - float noisevarab_b = SQR(realblue); + float interm_medT= (float) dnparams.chroma/10.0; bool execwavelet=true; - 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 + bool autoch=false; + if(noisevarL < 0.000007f && interm_medT < 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(settings->leveldnautsimpl==1 && dnparams.Cmethod!="MAN") execwavelet=true; + if(settings->leveldnautsimpl==0 && dnparams.C2method!="MAN") execwavelet=true; + if(settings->leveldnautsimpl==1 && (dnparams.Cmethod=="AUT" || dnparams.Cmethod=="PRE")) autoch=true; + if(settings->leveldnautsimpl==0 && dnparams.C2method=="AUTO" || dnparams.C2method=="PREV") autoch=true; + 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) wavelet_decomposition* Ldecomp; wavelet_decomposition* adecomp; wavelet_decomposition* bdecomp; + int schoice=0;//shrink method + if(dnparams.smethod=="shal") schoice=0; + else if(dnparams.smethod=="shalbi") schoice=2; int levwav=5; - float maxreal = max(realred2, realblue2); + float maxreal = max(realred, realblue); //increase the level of wavelet if user increase much or very much sliders if( maxreal < 8.f) levwav=5; else if( maxreal < 10.f)levwav=6; else if( maxreal < 15.f)levwav=7; else levwav=8;//maximum ==> I have increase Maxlevel in cplx_wavelet_dec.h from 8 to 9 + if(schoice==2) levwav+=settings->nrwavlevel;//increase level for enhanced mode + if(levwav>8) levwav=8; - 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(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==0) WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, noisevarchrom, width, height, mad_LL, mad_aa, mad_bb, noisevarab_r, noisevarab_b,labdn, lldenoiseutili, dnNoisCurve, dnNoisCCcurve, ccdenoiseutili, chaut, redaut, blueaut, maxredaut, maxblueaut, schoice, autoch);//enhance mode 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); + WaveletDenoiseAll_BiShrink(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, noisevarchrom, width, height, mad_LL, mad_aa, mad_bb, noisevarab_r, noisevarab_b,labdn, lldenoiseutili, dnNoisCurve, dnNoisCCcurve, ccdenoiseutili, chaut, redaut, blueaut, maxredaut, maxblueaut, schoice, autoch);//enhance mode + WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, noisevarchrom, width, height, mad_LL, mad_aa, mad_bb, noisevarab_r, noisevarab_b,labdn, lldenoiseutili, dnNoisCurve, dnNoisCCcurve, ccdenoiseutili, chaut ,redaut, blueaut, maxredaut, maxblueaut, schoice, autoch); } - /* 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); - } - */ - + float chresid,chmaxredresid,chmaxblueresid,chresidred, chresidblue; + //kall=0 call by Dcrop + resid=0.f;residred=0.f;residblue=0.f; + + if(kall==0) Noise_residual(*Ldecomp, *adecomp, *bdecomp, width, height, chresid, chmaxredresid,chmaxblueresid, chresidred, chresidblue, resid, residblue, residred, maxredresid, maxblueresid, nbresid); + //printf("NoiRESID=%3.1f maxR=%3.1f maxB=%3.1f red=%3.1f blue=%3.1f\n",chresid, chmaxredresid,chmaxblueresid, chresidred, chresidblue); + nresi=chresid; + highresi=chresid + 0.66f*(max(chmaxredresid,chmaxblueresid) - chresid);//evaluate sigma Ldecomp->reconstruct(labdn->data); delete Ldecomp; adecomp->reconstruct(labdn->data+datalen); @@ -787,9 +886,11 @@ float media(float *elements, int N) int metchoice=0; if(dnparams.methodmed=="Lonly") metchoice=1; else if(dnparams.methodmed=="Lab") metchoice=2; + else if(dnparams.methodmed=="ab") metchoice=3; + else if(dnparams.methodmed=="Lpab") metchoice=4; //median on Luminance Lab only - if( (metchoice==1 || metchoice==2) && dnparams.median) { + if( (metchoice==1 || metchoice==2 || metchoice==3 || metchoice==4) && dnparams.median) { //printf("Lab et Lonly \n"); for(int iteration=1;iteration<=dnparams.passes;iteration++){ //printf("pas=%i\n",iteration); @@ -801,24 +902,53 @@ float media(float *elements, int N) tmL[i] = new float[wid]; int methmedL=0; + int methmedAB=0; int borderL = 1; if(dnparams.medmethod=="soft") - methmedL=0; + {if(metchoice!=4) methmedL=methmedAB=0; + else {methmedL=0;methmedAB=0;} + } else if(dnparams.medmethod=="33") - methmedL=1; + {if(metchoice!=4) methmedL=methmedAB=1; + else {methmedL=0;methmedAB=1;borderL = 1;} + } + + // methmedL=methmedAB=1; else if(dnparams.medmethod=="55") { - methmedL = 3; + {if(metchoice!=4) methmedL=methmedAB=3; + else {methmedL=1;methmedAB=3;} + } + + + // methmedL =methmedAB= 3; borderL = 2; } else if(dnparams.medmethod=="55soft") { - methmedL = 2; + {if(metchoice!=4) methmedL=methmedAB=2; + else {methmedL=0;methmedAB=2;} + } + + // methmedL = methmedAB= 2; borderL = 2; } else if(dnparams.medmethod=="77") { - methmedL = 4; + {if(metchoice!=4) methmedL=methmedAB=4; + else {methmedL=1;methmedAB=4;} + } + + // methmedL = methmedAB=4; borderL = 3; + } + else if(dnparams.medmethod=="99") { + {if(metchoice!=4) methmedL=methmedAB=5; + else {methmedL=2;methmedAB=5;} + } + + // methmedL = methmedAB = 5; + borderL = 4; } - if (metchoice==1 || metchoice==2) + + if (metchoice==1 || metchoice==2 || metchoice==4) { /*printf("LONLY methmedL=%d\n", methmedL);*/ if(methmedL < 2) { @@ -856,7 +986,7 @@ float media(float *elements, int N) } else { for (int i=borderL; iL[i+ii][j+jj]; + } + } + fq_sort2(pp,81); + tmL[i][j]=pp[40];//9x9 + } + else if(methmedL == 3) for (int j=2; jL[i][j],labdn->L[i-1][j],labdn->L[i+1][j],labdn->L[i][j+1],labdn->L[i][j-1],labdn->L[i-1][j-1],labdn->L[i-1][j+1], labdn->L[i+1][j-1],labdn->L[i+1][j+1], @@ -885,6 +1027,7 @@ float media(float *elements, int N) } } + for(int i = borderL; i < hei-borderL; i++ ) { for(int j = borderL; j < wid-borderL; j++) { @@ -892,11 +1035,11 @@ float media(float *elements, int N) } } } - if(metchoice==2) {/*printf(" AB methmedL=%d\n", methmedL);*/ - if(methmedL < 2) { + if(metchoice==2 || metchoice==3 || metchoice==4) {/*printf(" AB methmedL=%d\n", methmedL);*/ + if(methmedAB < 2) { for (int i=1; ia[i][j] ,labdn->a[i-1][j], labdn->a[i+1][j] ,labdn->a[i][j+1],labdn->a[i][j-1], tmL[i][j]);//3x3 soft } @@ -908,8 +1051,8 @@ float media(float *elements, int N) } else { for (int i=borderL; ia[i+ii][j+jj]; + } + } + fq_sort2(pp,81); + tmL[i][j]=pp[40];//9 + } + + else if(methmedAB == 3) for (int j=2; ja[i][j],labdn->a[i-1][j],labdn->a[i+1][j],labdn->a[i][j+1],labdn->a[i][j-1],labdn->a[i-1][j-1],labdn->a[i-1][j+1], labdn->a[i+1][j-1],labdn->a[i+1][j+1], labdn->a[i-2][j],labdn->a[i+2][j],labdn->a[i][j+2],labdn->a[i][j-2],labdn->a[i-2][j-2],labdn->a[i-2][j+2],labdn->a[i+2][j-2],labdn->a[i+2][j+2], @@ -960,10 +1115,10 @@ float media(float *elements, int N) //b - if(methmedL < 2) { + if(methmedAB < 2) { for (int i=1; ib[i][j] ,labdn->b[i-1][j], labdn->b[i+1][j] ,labdn->b[i][j+1],labdn->b[i][j-1], tmL[i][j]);//3x3 soft } @@ -975,7 +1130,7 @@ float media(float *elements, int N) } else { for (int i=borderL; ib[i+ii][j+jj]; + } + } + fq_sort2(pp,81); + tmL[i][j]=pp[40];//9 + } + + else if(methmedAB == 3) for (int j=2; jb[i][j],labdn->b[i-1][j],labdn->b[i+1][j],labdn->b[i][j+1],labdn->b[i][j-1],labdn->b[i-1][j-1],labdn->b[i-1][j+1], labdn->b[i+1][j-1],labdn->b[i+1][j+1], labdn->b[i-2][j],labdn->b[i+2][j],labdn->b[i][j+2],labdn->b[i][j-2],labdn->b[i-2][j-2],labdn->b[i-2][j+2],labdn->b[i+2][j-2],labdn->b[i+2][j+2], @@ -1168,7 +1335,6 @@ float media(float *elements, int N) if (tileleft>0) Hmask[i] = mask; if (tilerightL[i1][j1]; a = labdn->a[i1][j1]; b = labdn->b[i1][j1]; + float c_h=sqrt(SQR(a)+SQR(b)); + if(c_h>3000.f){ + a*=1.f + Qhigh*realred/100.f; + b*=1.f + Qhigh*realblue/100.f; + } //convert XYZ Color::Lab2XYZ(L, a, b, X, Y, Z); //apply inverse gamma noise @@ -1227,6 +1398,12 @@ float media(float *elements, int N) Y = labdn->L[i1][j1]; X = (labdn->a[i1][j1]) + Y; Z = Y - (labdn->b[i1][j1]); + float c_h=sqrt(SQR(X)+SQR(Z)); + if(c_h>3000.f){ + X*=1.f + Qhigh*realred/100.f; + Z*=1.f + Qhigh*realblue/100.f; + } + X = X<32768.0f ? igamcurve[X] : (Color::gamma((float)X/32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); Y = Y<32768.0f ? igamcurve[Y] : (Color::gamma((float)Y/32768.0f, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0f); @@ -1252,6 +1429,12 @@ float media(float *elements, int N) L = labdn->L[i1][j1]; a = labdn->a[i1][j1]; b = labdn->b[i1][j1]; + float c_h=sqrt(SQR(a)+SQR(b)); + if(c_h>3000.f){ + a*=1.f + Qhigh*realred/100.f; + b*=1.f + Qhigh*realblue/100.f; + } + Color::Lab2XYZ(L, a, b, X, Y, Z); float factor = Vmask[i1]*Hmask[j1]; @@ -1278,6 +1461,11 @@ float media(float *elements, int N) delete [] noisevarlum[i]; delete [] noisevarlum; delete [] mad_LL; + for (int i=0; imaxredresid ) maxredresid=madaC; + if(madbC > maxblueresid) maxblueresid=madbC; + nbresid++; + + chresid=sqrt(resid/(2*nbresid)); + chmaxredresid=sqrt(maxredresid); + chmaxblueresid=sqrt(maxblueresid); + chresidred=sqrt(residred/nbresid); + chresidblue=sqrt(residblue/nbresid); + + + } + + + + } + delete [] madHisto; + + + +} SSEFUNCTION void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a, - 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) + wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float **noisevarlum, float **noisevarchrom, int width, int height, float *mad_LL, float *mad_aa, float *mad_bb, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve, const NoisCCcurve & dnNoisCCcurve, bool ccdenoiseutili, float &chaut, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, int schoice, bool autoch) { int maxlvl = WaveletCoeffs_L.maxlevel(); const float eps = 0.01f; // int max; // float parfrac = 0.05; - float madL[8][3], mada[8][3], madb[8][3]; - + float madaC,madbC; int * madHisto = new int[65536]; for (int lvl=0; lvl=0; lvl--) {//for levels less than max, use level diff to make edge mask //for (int lvl=0; lvl edge(Wlvl_L,Hlvl_L); //printf("\n level=%d \n",lvl); + if(autoch && noisevar_abr <=0.001f) noisevar_abr=0.02f; + if(autoch && noisevar_abb <=0.001f) noisevar_abb=0.02f; for (int dir=1; dir<4; dir++) { 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]; + float mad_ar = noisevar_abr*mada[lvl][dir-1]; + float mad_br = noisevar_abb*madb[lvl][dir-1]; + if (!ccdenoiseutili || dnNoisCCcurve.nonzeroc < 5.f ){ + for (int i=0; i 5.f ){ + // printf("OUI\n"); + for (int i=0; i0.001f || noisevar_abb>0.001f) { for(int i=0;i0.00001f) { - if (!lldenoiseutili && dnNoisCurve.nonzero < 7.f ) { + if (!lldenoiseutili || dnNoisCurve.nonzero < 7.f ) { for (int i=0; i 582=max - float mad_b = madb*noisevar_abb; + // float mad_a = mada*noisevar_abr; // noisevar_abr between 0..2.25=default 100=middle value ==> 582=max + // float mad_b = madb*noisevar_abb; // printf("noisevarabr=%f\n",noisevar_abr); + if(autoch && noisevar_abr <=0.001f) noisevar_abr=0.02f; + if(autoch && noisevar_abb <=0.001f) noisevar_abb=0.02f; + + if (!ccdenoiseutili || dnNoisCCcurve.nonzeroc < 5.f ){ // printf("Chroma NON\n"); - if (noisevar_abr>0.001f || noisevar_abb>0.001f ) { + for (int i=0; i 5.f ){ +// printf("chroma OUI\n"); + for (int i=0; i0.001f || noisevar_abb>0.001f ) { for(int i=0;i2*thresh_a ? 1 : (coeff_a2*thresh_b ? 1 : (coeff_b0.00001f) { if (!lldenoiseutili || dnNoisCurve.nonzero < 7.f ){//under 7 quasi no action - // printf("sans\n"); + // printf("Luma sans\n"); for (int i=0; i= 7.f) {//printf("avec\n"); + else {if (lldenoiseutili && dnNoisCurve.nonzero >= 7.f) { // printf("Luma avec\n"); for (int i=0; i maxchro) maxchro= noisevarchrom[i][j]; + chro+=noisevarchrom[i][j];nc++; + } + } + for (int i=0; i -0.8f && noisevarhue[i][j] < 2.0f && noisevarchrom[i][j] > 10000.f)//saturated red yellow + {red_yel+=noisevarchrom[i][j];nry++;} + if(noisevarhue[i][j] > 0.f && noisevarhue[i][j] < 1.6f && noisevarchrom[i][j] < 10000.f)//skin + {skin_c+=noisevarchrom[i][j];nsk++;} + + } + } + for (int i=0; i maxchred) maxchred=mada; + if(madb > maxchblue) maxchblue=madb; + if(mada < minchred) minchred=mada; + if(madb < minchblue) minchblue=madb; + nb++; + //here evaluation of automatic + // printf("WAL dir=%d mada=%4.0f madb=%4.0f skip_ab=%i minR=%4.0f minB=%4.0f nb=%d\n",dir, sqrt(mada),sqrt(madb), skip_ab, sqrt(minchred), sqrt(minchblue), nb); + mada=madb=0.f; + float reduc=1.f; + // if(schoice==2) reduc=0.6f; + if(schoice==2) reduc=(float) settings->nrhigh; + chaut=sqrt(reduc*chau/(nb + nb)); + redaut=sqrt(reduc*chred/nb); + blueaut=sqrt(reduc*chblue/nb); + maxredaut=sqrt(reduc*maxchred); + maxblueaut=sqrt(reduc*maxchblue); + minredaut=sqrt(reduc*minchred); + minblueaut=sqrt(reduc*minchblue); + Nb=nb; + } + } + // } + + delete[] sfave; + delete[] sfavea; + delete[] sfaveb; + delete[] WavCoeffsLtemp; + // delete[] mad_L; + + } + + + + void ImProcFunctions::WaveletDenoiseAll_info(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a, + wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float *mad_LL, float *mad_aa, float *mad_bb, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve, const NoisCCcurve & dnNoisCCcurve, bool ccdenoiseutili, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut,int schoice, bool autoch, + float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue ){ + + + + int maxlvl = WaveletCoeffs_L.maxlevel(); +// printf("maxlevel = %d\n",maxlvl); +//omp_set_nested(true); + for (int lvl=0; lvl TIF and JPG + if(gam <1.9f) gam=1.f - (1.9f-gam)/3.f;//minimum gamma 0.7 + else if (gam >= 1.9f && gam <= 3.f) gam=(1.4f/1.1f)*gam - 1.41818f; + } + gamslope = exp(log((double)gamthresh)/gam)/gamthresh; + if(perf) { + for (int i=0; i<65536; i++) { + gamcurve[i] = (Color::gamma((double)i/65535.0, gam, gamthresh, gamslope, 1.0, 0.0)) * 32768.0f; + } + } + else { + for (int i=0; i<65536; i++) { + gamcurve[i] = (Color::gamman((double)i/65535.0,gam)) * 32768.0f; + } + } + + } + +void ImProcFunctions::calcautodn_info (float &chaut, float &delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc) + {//lissage = 1 more action + float reducdelta=1.f; + if(params->dirpyrDenoise.smethod=="shalbi") reducdelta=(float) settings->nrhigh; + + chaut = (chaut*Nb-maxmax)/(Nb-1);//suppress maximum for chaut calcul + if(redyel>5000.f || skinc > 1000.f && nsknc < 0.4f && chromina > 3000.f ) chaut *=0.45f;//reduct action in red zone, except skin for high / med chroma + else if(redyel>12000.f || skinc > 1200.f && nsknc < 0.3f && chromina > 3000.f ) chaut *=0.3f; + + if(mode==0 || mode==2) {//Preview or Auto multizone + if(chromina > 10000.f) chaut*=0.7f;//decrease action for high chroma (visible noise) + else if(chromina > 6000.f) chaut*=0.9f; + else if(chromina < 3000.f) chaut*=1.2f;//increase action in low chroma==> 1.2 /==>2.0 ==> curve CC + else if(chromina < 2000.f) chaut*=1.5f;//increase action in low chroma==> 1.5 / ==>2.7 + + if(lumema < 2500.f) chaut*=1.3f;//increase action for low light + else if(lumema < 5000.f) chaut*=1.2f; + else if(lumema > 20000.f) chaut*=0.9f;//decrease for high light + } + else if(mode==1){//auto ==> less coefficient because interaction + if(chromina > 10000.f) chaut*=0.8f;//decrease action for high chroma (visible noise) + else if(chromina > 6000.f) chaut*=0.9f; + else if(chromina < 3000.f) chaut*=1.5f;//increase action in low chroma + else if(chromina < 2000.f) chaut*=2.2f;//increase action in low chroma + if(lumema < 2500.f) chaut*=1.2f;//increase action for low light + else if(lumema < 5000.f) chaut*=1.1f; + else if(lumema > 20000.f) chaut*=0.9f;//decrease for high light + + } + if(levaut==0) {//Low denoise + if(chaut > 300.f) chaut = 0.714286f*chaut + 85.71428f; + } + delta = maxmax-chaut; + delta*=reducdelta; + + if(lissage==1 || lissage==2) { + if(chaut < 200.f && delta < 200.f ) delta*=0.95f; + else if(chaut < 200.f && delta < 400.f ) delta*=0.5f; + else if(chaut < 200.f && delta >= 400.f ) delta=200.f; + else if(chaut < 400.f && delta < 400.f ) delta*=0.4f; + else if(chaut < 400.f && delta >= 400.f ) delta=120.f; + else if(chaut < 550.f) delta*=0.15f; + else if(chaut < 650.f) delta*=0.1f; + else if(chaut >= 650.f) delta*=0.07f; + if(mode==0 || mode==2) {//Preview or Auto multizone + if(chromina < 6000.f) delta*=1.4f;//increase maxi + if(lumema < 5000.f) delta*=1.4f; + } + else if(mode==1) {//Auto + if(chromina < 6000.f) delta*=1.2f;//increase maxi + if(lumema < 5000.f) delta*=1.2f; + } + } + if(lissage==0) { + if(chaut < 200.f && delta < 200.f ) delta*=0.95f; + else if(chaut < 200.f && delta < 400.f ) delta*=0.7f; + else if(chaut < 200.f && delta >= 400.f ) delta=280.f; + else if(chaut < 400.f && delta < 400.f ) delta*=0.6f; + else if(chaut < 400.f && delta >= 400.f ) delta=200.f; + else if(chaut < 550.f) delta*=0.3f; + else if(chaut < 650.f) delta*=0.2f; + else if(chaut >= 650.f) delta*=0.15f; + if(mode==0 || mode==2) {//Preview or Auto multizone + if(chromina < 6000.f) delta*=1.4f;//increase maxi + if(lumema < 5000.f) delta*=1.4f; + } + else if(mode==1) {//Auto + if(chromina < 6000.f) delta*=1.2f;//increase maxi + if(lumema < 5000.f) delta*=1.2f; + } + } + + } + + void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * dst,Imagefloat * provicalc, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp, const NoisCurve & dnNoisCurve, bool lldenoiseutili, const NoisCCcurve & dnNoisCCcurve, bool ccdenoiseutili, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, float &nresi, float &highresi, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc) + { +// StopWatch Stop1("RGB_denoise_info"); + int hei,wid; +// float LLum,AAum,BBum; + float** lumcalc; + float** acalc; + float** bcalc; + if(lldenoiseutili || ccdenoiseutili) { + hei=provicalc->height; + wid=provicalc->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 = provicalc->g(ii,jj); + float BL = provicalc->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; + acalc[ii][jj]=AAum; + bcalc[ii][jj]=BBum; + } + } + +} + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + const short int imheight=src->height, imwidth=src->width; + if (dnparams.luma==0 && dnparams.chroma==0 && !dnparams.median ) { + //nothing to do; copy src to dst or do nothing in case src == dst + if(src != dst) + memcpy(dst->data,src->data,dst->width*dst->height*3*sizeof(float)); + return; + } + + if (dnparams.luma!=0 || dnparams.chroma!=0 || dnparams.methodmed=="Lab" || dnparams.methodmed=="Lonly" ) { + perf=false; + if(dnparams.dmethod=="RGB") perf=true;//RGB mode + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // gamma transform for input data +// LUTf gamcurve(65536,0); +// float gam, gamthresh, gamslope; +// RGB_denoise_infoGamCurve(dnparams, isRAW, gamcurve, gam, gamthresh, gamslope); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + const float gain = pow (2.0f, float(expcomp)); + float incr=1.f; + float noisevar_Ldetail = SQR((float)(SQR(100.-dnparams.Ldetail) + 50.*(100.-dnparams.Ldetail)) * TS * 0.5f * incr); + bool enhance_denoise = dnparams.enhance; + int gamlab = settings->denoiselabgamma;//gamma lab essentialy for Luminance detail + if(gamlab > 2) gamlab=2; + +/* + array2D tilemask_in(TS,TS); + array2D tilemask_out(TS,TS); + + const int border = MAX(2,TS/16); + + + for (int i=0; iTS/2 ? i-TS+1 : i)); + float vmask = (i1TS/2 ? j-TS+1 : j)); + tilemask_in[i][j] = (vmask * (j1data[n] = 0; + + int tilesize; + int overlap; + if(settings->leveldnti ==0) { + tilesize = 1024; + overlap = 128; + } + if(settings->leveldnti ==1) { + tilesize = 768; + overlap = 96; + } + + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + + //always no Tiles + int kall=0; + Tile_calc (tilesize, overlap, kall, imwidth, imheight, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + { + + //DCT block data storage + TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); + + double wp[3][3] = { + {wprof[0][0],wprof[0][1],wprof[0][2]}, + {wprof[1][0],wprof[1][1],wprof[1][2]}, + {wprof[2][0],wprof[2][1],wprof[2][2]} + }; + + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + //inverse matrix user select + double wip[3][3] = { + {wiprof[0][0],wiprof[0][1],wiprof[0][2]}, + {wiprof[1][0],wiprof[1][1],wiprof[1][2]}, + {wiprof[2][0],wiprof[2][1],wiprof[2][2]} + }; + + float chau=0.f; + float chred=0.f; + float chblue=0.f; + float maxchred=0.f; + float maxchblue=0.f; + float minchred =100000000.f; + float minchblue=100000000.f; + int nb=0; +// resid=0.f; +// nbresid=0; +// maxredresid=0.f; +// maxblueresid=0.f; +// residred=0.f; +// residblue=0.f; + int comptlevel=0; +// static MyMutex FftwMutex; +// MyMutex::MyLock lock(FftwMutex); + + + for (int tiletop=0; tiletop 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))); + float noisevarab_b, noisevarab_r; + bool ponder=false; + + float realred2, realred, realblue, realblue2; + float interm_med =(float) dnparams.chroma/10.0; + float intermred, intermblue; + if(dnparams.redchro > 0.) intermred=(dnparams.redchro/10.); else intermred= (float) dnparams.redchro/7.0;//increase slower than linear for more sensit + if(dnparams.bluechro > 0.) intermblue=(dnparams.bluechro/10.); else intermblue= (float) dnparams.bluechro/7.0;//increase slower than linear for more sensit + realred = interm_med + intermred; if (realred < 0.f) realred=0.001f; + realblue = interm_med + intermblue; if (realblue < 0.f) realblue=0.001f; + //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 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) { + Llum=lumcalc[i][j]; + } + if(dnNoisCCcurve) { + alum=acalc[i][j]; + blum=bcalc[i][j]; + } + //finally I opted fot gamma55 and with options we can change + if (gamlab == 0) {// options 12/2013 + R_ = Color::igammatab_26_11[R_]; + G_ = Color::igammatab_26_11[G_]; + B_ = Color::igammatab_26_11[B_]; + } + else if (gamlab == 1) { + //other new gamma 4 5 + R_ = Color::igammatab_4[R_]; + G_ = Color::igammatab_4[G_]; + B_ = Color::igammatab_4[B_]; + } + else if (gamlab == 2) { + //new gamma 5.5 10 better for detail luminance..it is a compromise...which depends on the image (distribution BL, ML, HL ...) + R_ = Color::igammatab_55[R_]; + G_ = Color::igammatab_55[G_]; + B_ = Color::igammatab_55[B_]; + } + //apply gamma noise standard (slider) + R_ = R_<65535.0f ? gamcurve[R_] : (Color::gamman((double)R_/65535.0, gam)*32768.0f); + G_ = G_<65535.0f ? gamcurve[G_] : (Color::gamman((double)G_/65535.0, gam)*32768.0f); + B_ = B_<65535.0f ? gamcurve[B_] : (Color::gamman((double)B_/65535.0, gam)*32768.0f); + //true conversion xyz=>Lab + float L,a,b; + float X,Y,Z; + Color::rgbxyz(R_,G_,B_,X,Y,Z,wp); + + //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]= kN;// SQR((ki/125.f)*(1.f+ki/25.f)); + } + noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f)); + // chroma + noisevarab_r = SQR(realred); + noisevarab_b = SQR(realblue); + + if(dnNoisCCcurve) { + float aN=alum; + float bN=blum; + float epsic=0.01f; + float kN=Llum;//with no gamma and take into account working profile + if(kN<2.f) kN=2.f;//avoid divided by zero + if(kN>32768.f) kN=32768.f; // not strictly necessary + + float cN=sqrt(SQR(aN)+SQR(bN)); + float hN=xatan2f(bN,aN); + if(cN < 100.f) cN=100.f;//avoid divided by zero + float Cinterm=1.f + 10.f*dnNoisCCcurve.lutNoisCCcurve[(cN/48000.f)*500.f];//C=f(C) + noisevarchrom[i1][j1]=cN; + noisevarhue[i1][j1]=hN; + + } + //end chroma + + labdn->L[i1][j1] = L; + labdn->a[i1][j1] = a; + labdn->b[i1][j1] = b; +// Lin[i1][j1] = L; +// totwt[i1][j1] = 0; + } + } + } + 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) { + Llum=lumcalc[i][j]; + } + if(dnNoisCCcurve) { + alum=acalc[i][j]; + blum=bcalc[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]= kN;//SQR((ki/125.f)*(1.f+ki/25.f)); + } + noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f)); + noisevarab_r = SQR(realred); + noisevarab_b = SQR(realblue); + if(dnNoisCCcurve) { + float aN=alum; + float bN=blum; + float epsic=0.01f; + float hN=xatan2f(bN,aN); + + float cN=sqrt(SQR(aN)+SQR(bN)); + if(cN < 100.f) cN=100.f;//avoid divided by zero + float Cinterm=1.f + 10.f*dnNoisCCcurve.lutNoisCCcurve[(cN/48000.f)*500.f]; + //noisevarchrom[i1][j1]=0.5f*(noisevarab_b+noisevarab_r)*(Cinterm*Cinterm); + noisevarchrom[i1][j1]=cN; + noisevarhue[i1][j1]=hN; + } + //end chroma + + labdn->L[i1][j1] = Y; + labdn->a[i1][j1] = (X-Y); + labdn->b[i1][j1] = (Y-Z); + +// Ldetail[i1][j1] = 0; +// Lin[i1][j1] = Y; +// totwt[i1][j1] = 0; + } + } + + } + + } 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 + float rtmp = Color::igammatab_srgb[ src->r(i,j) ]; + float gtmp = Color::igammatab_srgb[ src->g(i,j) ]; + float btmp = Color::igammatab_srgb[ src->b(i,j) ]; + //modification Jacques feb 2013 + // gamma slider different from raw + rtmp = rtmp<65535.0f ? gamcurve[rtmp] : (Color::gamman((double)rtmp/65535.0, gam)*32768.0f); + gtmp = gtmp<65535.0f ? gamcurve[gtmp] : (Color::gamman((double)gtmp/65535.0, gam)*32768.0f); + btmp = btmp<65535.0f ? gamcurve[btmp] : (Color::gamman((double)btmp/65535.0, gam)*32768.0f); + + noisevarab_r = SQR(realred); + noisevarab_b = SQR(realblue); + + + float X,Y,Z; + Color::rgbxyz(rtmp,gtmp,btmp,X,Y,Z,wp); + + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, a, b); + float Llum,alum,blum; + if(dnNoisCurve || dnNoisCCcurve) { + 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]=kN;//SQR((ki/125.f)*(1.f+ki/25.f)); + } + noisevarL = SQR((noiseluma/125.f)*(1.f+noiseluma/25.f)); + if(dnNoisCCcurve) { + float aN=alum; + float bN=blum; + float epsic=0.01f; + float hN=xatan2f(bN,aN); + + float cN=sqrt(SQR(aN)+SQR(bN)); + if(cN < 100.f) cN=100.f;//avoid divided by zero + float Cinterm=1.f + 10.f*dnNoisCCcurve.lutNoisCCcurve[(cN/48000.f)*500.f]; + //noisevarchrom[i1][j1]=0.5f*(noisevarab_b+noisevarab_r)*(Cinterm*Cinterm); + noisevarchrom[i1][j1]=cN; + noisevarhue[i1][j1]=hN; + + + } + + labdn->L[i1][j1] = L; + labdn->a[i1][j1] = a; + labdn->b[i1][j1] = b; + +// Ldetail[i1][j1] = 0; +// Lin[i1][j1] = L; + +// totwt[i1][j1] = 0; + } + } + } + /* if (dnparams.luma>0.01) { + impulse_nr (labdn, float(MIN(50.0,dnparams.luma))/20.0f); + } +*/ + int datalen = labdn->W * labdn->H; + + //now perform basic wavelet denoise + //last two arguments of wavelet decomposition are max number of wavelet decomposition levels; + //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. + noisevarab_r = SQR(realred) + 0.01f; + noisevarab_b = SQR(realblue) + 0.01f; + + bool execwavelet=true; + 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) + wavelet_decomposition* Ldecomp; + wavelet_decomposition* adecomp; + wavelet_decomposition* bdecomp; + int schoice=0;//shrink method + + if(dnparams.smethod=="shal") schoice=0; + else if(dnparams.smethod=="shalbi") schoice=2; + + int levwav=5; + float maxreal = max(realred, realblue); + //increase the level of wavelet if user increase much or very much sliders + + + // 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 ); + bool autoch = dnparams.autochroma; + if(comptlevel==0) WaveletDenoiseAll_info(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarlum, noisevarchrom, noisevarhue, width, height, mad_LL, mad_aa, mad_bb, noisevarab_r, noisevarab_b,labdn, lldenoiseutili, dnNoisCurve, dnNoisCCcurve, ccdenoiseutili, chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, schoice, autoch, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc,maxchred, maxchblue, minchred, minchblue, nb,chau ,chred, chblue);//enhance mode + comptlevel+=1; + float chresid,chmaxredresid,chmaxblueresid,chresidred, chresidblue; + nresi=chresid; + highresi=chresid + 0.66f*(max(chmaxredresid,chmaxblueresid) - chresid);//evaluate sigma + delete Ldecomp; + delete adecomp; + delete bdecomp; + } + } + + + + delete labdn; + // delete noiseh; + for (int i=0; i& llcurvePoints, LUTf & Noisecurve,int skip){ +// add curve Denoise : C=f(C) +void CurveFactory::denoiseCC ( bool & ccdenoiseutili,const std::vector& cccurvePoints, LUTf & NoiseCCcurve,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; + for (int i=0; i<48000; i++) { + dCcurve[i] = (float)i / 47999.0; } needed = false; - if (!llcurvePoints.empty() && llcurvePoints[0]!=0) { - dCurve = new DiagonalCurve (llcurvePoints, CURVES_MIN_POLY_POINTS/skip); + if (!cccurvePoints.empty() && cccurvePoints[0]!=0) { + dCurve = new DiagonalCurve (cccurvePoints, CURVES_MIN_POLY_POINTS/skip); if (dCurve && !dCurve->isIdentity()) - {needed = true;lldenoiseutili=true;} + {needed = true;ccdenoiseutili=true;} } - fillCurveArray(dCurve, Noisecurve, skip, needed); - //Noisecurve.dump("Noise"); + fillCurveArray(dCurve, NoiseCCcurve, skip, needed); + //NoiseCCcurve.dump("Noise"); if (dCurve) { delete dCurve; @@ -1191,6 +1191,38 @@ void OpacityCurve::Set(const std::vector &curvePoints, bool &opautili) { } } +void NoisCCcurve::Reset() { + lutNoisCCcurve.reset(); +} + +void NoisCCcurve::Set(const Curve *pCurve) { + if (pCurve->isIdentity()) { + lutNoisCCcurve.reset(); // raise this value if the quality suffers from this number of samples + return; + } + lutNoisCCcurve(501); // raise this value if the quality suffers from this number of samples + nonzeroc=0.f; + for (int i=0; i<501; i++) { + lutNoisCCcurve[i] = pCurve->getVal(double(i)/500.); + if(lutNoisCCcurve[i] < 0.1f) lutNoisCCcurve[i]=0.1f;//avoid 0.f for wavelet : under 0.01f quasi no action for each value + nonzeroc+=lutNoisCCcurve[i];}//minima for Wavelet about 6.f or 7.f quasi no action + //lutNoisCCcurve.dump("NoisCC"); +} +void NoisCCcurve::Set(const std::vector &curvePoints, bool &ccdenoiseutili) { + FlatCurve* tcurve = NULL; + + if (!curvePoints.empty() && curvePoints[0]>FCT_Linear && curvePoints[0]setIdentityValue(0.); + } + if (tcurve) { + Set(tcurve);ccdenoiseutili=true; + delete tcurve; + tcurve = NULL; + } +} + + void NoisCurve::Reset() { lutNoisCurve.reset(); } diff --git a/rtengine/curves.h b/rtengine/curves.h index 63550bcc9..2e88b1712 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -220,7 +220,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 denoiseCC ( bool & ccdenoiseutili, const std::vector& cccurvePoints, LUTf & NoiseCCcurve,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, @@ -385,6 +385,19 @@ class NoisCurve { operator bool (void) const { return lutNoisCurve; } }; +class NoisCCcurve { + public: + LUTf lutNoisCCcurve; // 0xffff range + float nonzeroc; + virtual ~NoisCCcurve() {}; + + void Reset(); + void Set(const Curve *pCurve); + void Set(const std::vector &curvePoints, bool &ccdenoiseutili); + + operator bool (void) const { return lutNoisCCcurve; } +}; + class ColorGradientCurve { public: LUTf lut1; // [0.;1.] range (float values) diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 882b6d0ff..98d466df1 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -23,6 +23,7 @@ #include "refreshmap.h" #include "rt_math.h" #include "colortemp.h" +//#include "../rtgui/cropguilistener.h" // "ceil" rounding #define SKIPS(a,b) ((a) / (b) + ((a) % (b) > 0)) @@ -112,6 +113,7 @@ void Crop::update (int todo) { MyMutex::MyLock cropLock(cropMutex); ProcParams& params = parent->params; + // CropGUIListener* cropgl; // No need to update todo here, since it has already been changed in ImprocCoordinator::updatePreviewImage, // and Crop::update ask to do ALL anyway @@ -121,7 +123,6 @@ void Crop::update (int todo) { bool overrideWindow = false; if (cropImageListener) overrideWindow = cropImageListener->getWindow (wx, wy, ww, wh, ws); - // re-allocate sub-images and arrays if their dimensions changed bool needsinitupdate = false; if (!overrideWindow) @@ -134,8 +135,10 @@ void Crop::update (int todo) { // Tells to the ImProcFunctions' tool what is the preview scale, which may lead to some simplifications parent->ipf.setScale (skip); - + Imagefloat* baseCrop = origCrop; + int widIm = parent->fw;//full image + int heiIm = parent->fh; bool needstransform = parent->ipf.needsTransform(); @@ -152,31 +155,465 @@ void Crop::update (int todo) { if (!needsinitupdate) setCropSizes (rqcropx, rqcropy, rqcropw, rqcroph, skip, true); - PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); - parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); - //ColorTemp::CAT02 (origCrop, ¶ms) ; + + // printf("x=%d y=%d crow=%d croh=%d skip=%d\n",rqcropx, rqcropy, rqcropw, rqcroph, skip); + // printf("trafx=%d trafyy=%d trafwsk=%d trafHs=%d \n",trafx, trafy, trafw*skip, trafh*skip); + + int skipP=1;//force Skip for noise evaluation Imagefloat *calclum;//for Luminance denoise curve NoisCurve dnNoisCurve; + NoisCCcurve dnNoisCCcurve; bool lldenoiseutili=false; - params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoiseutili); - if(lldenoiseutili && skip==1 && params.dirpyrDenoise.enabled) {//only allocate memory if enabled and skip + bool ccdenoiseutili=false; + float autoNR = (float) settings->nrauto;// + float autoNRmax = (float) settings->nrautomax;// + float autohigh = (float) settings->nrhigh;// + + params.dirpyrDenoise.getCurves(dnNoisCurve, dnNoisCCcurve, lldenoiseutili, ccdenoiseutili); + + int tilesize; + int overlap; + if(settings->leveldnti ==0) { + tilesize = 1024; + overlap = 128; + } + if(settings->leveldnti ==1) { + tilesize = 768; + overlap = 96; + } + + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + int kall=2; + + parent->ipf.Tile_calc (tilesize, overlap, kall, widIm, heiIm, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + kall=0; + + int nbtl=numtiles_W*numtiles_H; + float *ch_M = new float [9];//allocate memory + float *max_r = new float [9]; + float *max_b = new float [9]; + float *min_b = new float [9]; + float *min_r = new float [9]; + float *lumL = new float [9]; + float *chromC = new float [9]; + float *ry = new float [9]; + float *sk = new float [9]; + float *pcsk = new float [9]; + int *centerTile_X = new int [numtiles_W]; + int *centerTile_Y = new int [numtiles_H]; + for(int cX=0;cXleveldnautsimpl==1){ + if(params.dirpyrDenoise.Cmethod=="MAN" || params.dirpyrDenoise.Cmethod=="PON" ) { + PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); + parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); + } + } + else { + if(params.dirpyrDenoise.C2method=="MANU") { + PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); + parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); + } + + } + /* + if(params.dirpyrDenoise.Cmethod=="PON") { + MyTime t1dce,t2dce; + t1dce.set(); + + int crW=100;//crop noise width + int crH=100;//crop noise height + Imagefloat *origCropPart;//init auto noise + origCropPart = new Imagefloat (crW, crH);//allocate memory + + int skipP=1; + if (skip==1 && params.dirpyrDenoise.enabled) {//evaluate Noise + + for(int wcr=0;wcrimgsrc->getImage (parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw ); + + Imagefloat *provi; + Imagefloat *provicalc; + provi = new Imagefloat (crW, crH); + if(origCropPart != provi) + origCropPart->copyData(provi); + provicalc = new Imagefloat (crW, crH); + if(origCropPart != provicalc) + origCropPart->copyData(provicalc); + parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB, params.raw);//for denoise luminance curve + float maxr=0.f; + float maxb=0.f; + + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L; + chaut=0.f;redaut=0.f; blueaut=0.f; maxredaut=0.f; maxblueaut=0.f;chromina=0.f; sigma=0.f; + parent->ipf.RGB_denoise_info(provi, provi, provicalc, parent->imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve,lldenoiseutili, dnNoisCCcurve,ccdenoiseutili, chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L); + //printf("DCROP skip=%d cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f\n",skip, chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema); + if(maxredaut > maxblueaut) { + maxr=(maxredaut-chaut)/(autoNRmax/2.f); + if(minblueaut <= minredaut && minblueaut < chaut) maxb=(-chaut+minblueaut)/autoNRmax; + } + else { + maxb=(maxblueaut-chaut)/(autoNRmax/2.f); + if(minredaut <= minblueaut && minredaut < chaut) maxr=(-chaut+minredaut)/autoNRmax; + }//maxb mxr - empirical evaluation red / blue + + ch_M[hcr*numtiles_W + wcr]=chaut/autoNR; + max_r[hcr*numtiles_W + wcr]=maxr; + max_b[hcr*numtiles_W + wcr]=maxb; + + delete provi; + + } + } + + } + delete origCropPart; + if (settings->verbose) { + t2dce.set(); + printf("Info denoise ponderated performed in %d usec:\n", t2dce.etime(t1dce)); + } + + } + */ + + if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="PRE") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="PREV")) { + + PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); + parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); + float lowdenoise=1.f; + int levaut=settings->leveldnaut; + if(levaut==1) //Standard + lowdenoise=0.7f; + int CenterPreview_X=trafx+(trafw*skip)/2; + int CenterPreview_Y=trafy+(trafh*skip)/2; + int minimuX=20000; + int minimuY=20000; + int poscenterX; + int poscenterY; + for(int cc=0;ccleveldnv ==0) {crW=100;crH=100;} + if(settings->leveldnv ==1) {crW=250;crH=250;} + // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview + if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(tileHskip/2);} + if(settings->leveldnv ==3) {crW=tileWskip-10;crH=tileHskip-10;} + + + if (skip==1 && params.dirpyrDenoise.enabled) { + float adjustr=1.f; + if (params.icm.working=="ProPhoto") {adjustr =1.f;} + else if (params.icm.working=="Adobe RGB") {adjustr = 1.f/1.3f;} + else if (params.icm.working=="sRGB") {adjustr = 1.f/1.3f;} + else if (params.icm.working=="WideGamut") {adjustr =1.f/1.1f;} + else if (params.icm.working=="Beta RGB") {adjustr =1.f/1.2f;} + else if (params.icm.working=="BestRGB") {adjustr =1.f/1.2f;} + else if (params.icm.working=="BruceRGB") {adjustr =1.f/1.2f;} + if(parent->adnListener) parent->adnListener->noiseTilePrev (centerTile_X[poscenterX], centerTile_Y[poscenterY],CenterPreview_X,CenterPreview_Y,crW, trafw*skip); + // I have tried "blind" some solutions..to move review ...but GUI is not my truc ! + // int W,H; + // cropgl->cropMoved (centerTile_X[poscenterX],centerTile_Y[poscenterY] , W, H); + // cropImageListener->setPosition (int x, int y, bool update=true); + // bool update; + // cropImageListener->setPosition (centerTile_X[poscenterX],centerTile_Y[poscenterY] , true); + //setCropSizes (centerTile_X[poscenterX], centerTile_Y[poscenterY], trafw*skip,trafh*skip , skip, true); + + Imagefloat *provi; + Imagefloat *provicalc; + provi = new Imagefloat (cropw, croph);// + if(origCrop != provi) + origCrop->copyData(provi); + provicalc = new Imagefloat (cropw, croph);//for Luminance denoise curve + if(origCrop != provicalc) + origCrop->copyData(provicalc); + + parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB, params.raw);//for denoise luminance curve + + float maxr=0.f; + float maxb=0.f; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + int Nb; + + chaut=0.f;redaut=0.f; blueaut=0.f; maxredaut=0.f; maxblueaut=0.f;minredaut=0.f; minblueaut=0.f; + LUTf gamcurve(65536,0); + float gam, gamthresh, gamslope; + parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); + + parent->ipf.RGB_denoise_info(provi, provi, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve,lldenoiseutili, dnNoisCCcurve,ccdenoiseutili, chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut,nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + printf("redy=%f skin=%f pcskin=%f\n",redyel, skinc,nsknc); + printf("DCROP skip=%d cha=%4.0f Nb=%d red=%4.0f bl=%4.0f redM=%4.0f bluM=%4.0f L=%4.0f sigL=%4.0f Ch=%4.0f Si=%4.0f\n",skip, chaut,Nb, redaut,blueaut, maxredaut, maxblueaut, lumema, sigma_L, chromina, sigma); + float multip=1.f; + if(!parent->imgsrc->isRAW()) multip=2.f;//take into account gamma for TIF / JPG approximate value...not good for gamma=1 + + float maxmax=max(maxredaut,maxblueaut); + float delta; + int mode=0; + // float redyel, skinc, nsknc; + int lissage=settings->leveldnliss; + parent->ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc); + + + if(maxredaut > maxblueaut) { + // maxr=(maxredaut-chaut)/((autoNRmax*multip*adjustr)/2.f); + maxr=(delta)/((autoNRmax*multip*adjustr*lowdenoise)/2.f); + if(minblueaut <= minredaut && minblueaut < chaut) maxb=(-chaut+minblueaut)/(autoNRmax*multip*adjustr*lowdenoise); + } + else { + // maxb=(maxblueaut-chaut)/((autoNRmax*multip*adjustr)/2.f); + maxb=(delta)/((autoNRmax*multip*adjustr*lowdenoise)/2.f); + if(minredaut <= minblueaut && minredaut < chaut) maxr=(-chaut+minredaut)/(autoNRmax*multip*adjustr*lowdenoise); + }//maxb mxr - empirical evaluation red / blue + + + params.dirpyrDenoise.chroma=chaut/(autoNR*multip*adjustr*lowdenoise); + params.dirpyrDenoise.redchro=maxr; + params.dirpyrDenoise.bluechro=maxb; + if(parent->adnListener) parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro); + + delete provi; + } + + } + + if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="AUT") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="AUTO")) { + + MyTime t1aue,t2aue; + t1aue.set(); + + int crW,crH; + if(settings->leveldnv ==0) {crW=100;crH=100;} + if(settings->leveldnv ==1) {crW=250;crH=250;} + // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int((tileWskip/2));}//adapted to scale of preview + if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(tileHskip/2);} + if(settings->leveldnv ==3) {crW=tileWskip-10;crH=tileHskip-10;} + + float lowdenoise=1.f; + int levaut=settings->leveldnaut; + if(levaut==1) //Standard + lowdenoise=0.7f; + + + if (skip==1 && params.dirpyrDenoise.enabled) {//evaluate Noise + LUTf gamcurve(65536,0); + float gam, gamthresh, gamslope; + parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); + int Nb; + + #pragma omp parallel + { + Imagefloat *origCropPart;//init auto noise + origCropPart = new Imagefloat (crW, crH);//allocate memory + Imagefloat *provi; + Imagefloat *provicalc; + provi = new Imagefloat (crW, crH); + provicalc = new Imagefloat (crW, crH); + + int coordW[3];//coordonate of part of image to mesure noise + int coordH[3]; + int begW=50; + int begH=50; + coordW[0]=begW;coordW[1]=widIm/2-crW/2;coordW[2]=widIm-crW-begW; + coordH[0]=begH;coordH[1]=heiIm/2-crH/2;coordH[2]=heiIm-crH-begH; + #pragma omp for schedule(dynamic) collapse(2) nowait + for(int wcr=0;wcr<=2;wcr++) { + for(int hcr=0;hcr<=2;hcr++) { + PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, skipP); + parent->imgsrc->getImage (parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw ); + + if(origCropPart != provi) + origCropPart->copyData(provi); + if(origCropPart != provicalc) + origCropPart->copyData(provicalc); + parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB, params.raw);//for denoise luminance curve + //float maxr=0.f; + //float maxb=0.f; + float pondcorrec=1.0f; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + chaut=0.f;redaut=0.f; blueaut=0.f; maxredaut=0.f; maxblueaut=0.f;chromina=0.f; sigma=0.f; + parent->ipf.RGB_denoise_info(provi, provi, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve,lldenoiseutili, dnNoisCCcurve,ccdenoiseutili, chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + + + //printf("DCROP skip=%d cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f\n",skip, chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema); + ch_M[hcr*3 + wcr]=pondcorrec*chaut; + max_r[hcr*3 + wcr]=pondcorrec*maxredaut; + max_b[hcr*3 + wcr]=pondcorrec*maxblueaut; + min_r[hcr*3 + wcr]=pondcorrec*minredaut; + min_b[hcr*3 + wcr]=pondcorrec*minblueaut; + lumL[hcr*3 + wcr]=lumema; + chromC[hcr*3 + wcr]=chromina; + ry[hcr*3 + wcr]=redyel; + sk[hcr*3 + wcr]=skinc; + pcsk[hcr*3 + wcr]=nsknc; + + } + } + delete provicalc; + delete provi; + delete origCropPart; + } + float chM=0.f; + float MaxR=0.f; + float MaxB=0.f; + float MinR=100000000000.f; + float MinB=100000000000.f; + float maxr=0.f; + float maxb=0.f; + float Max_R[9]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f}; + float Max_B[9]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f}; + float Min_R[9]; + float Min_B[9]; + float MaxRMoy=0.f; + float MaxBMoy=0.f; + float MinRMoy=0.f; + float MinBMoy=0.f; + + float multip=1.f; + if(!parent->imgsrc->isRAW()) multip=2.f;//take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + float adjustr=1.f; + if (params.icm.working=="ProPhoto") {adjustr =1.f;}// + else if (params.icm.working=="Adobe RGB") {adjustr = 1.f/1.3f;} + else if (params.icm.working=="sRGB") {adjustr = 1.f/1.3f;} + else if (params.icm.working=="WideGamut") {adjustr =1.f/1.1f;} + else if (params.icm.working=="Beta RGB") {adjustr =1.f/1.2f;} + else if (params.icm.working=="BestRGB") {adjustr =1.f/1.2f;} + else if (params.icm.working=="BruceRGB") {adjustr =1.f/1.2f;} + + float maxmax; + float minmin; + float delta[9]; + int mode=1; + float redyel, skinc, nsknc; + int lissage=settings->leveldnliss; + for(int k=0;k<9;k++) { + maxmax=max(max_r[k],max_b[k]); + parent->ipf.calcautodn_info (ch_M[k], delta[k], Nb, levaut, maxmax,lumL[k],chromC[k], mode, lissage, ry[k], sk[k], pcsk[k]); + // printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]); + } + for(int k=0;k<9;k++) { + if(max_r[k] > max_b[k]) { + minmin=min(min_r[k],min_b[k]); + Max_R[k]=(delta[k])/((autoNRmax*multip*adjustr*lowdenoise)/2.f); + Min_B[k]= -(ch_M[k]- min_b[k])/(autoNRmax*multip*adjustr*lowdenoise); + Max_B[k]=0.f; + Min_R[k]=0.f; + } + else { + minmin=min(min_r[k],min_b[k]); + Max_B[k]=(delta[k])/((autoNRmax*multip*adjustr*lowdenoise)/2.f); + Min_R[k]=- (ch_M[k]-min_r[k]) / (autoNRmax*multip*adjustr*lowdenoise); + Min_B[k]=0.f; + Max_R[k]=0.f; + + } + } + + for(int k=0;k<9;k++) { + // printf("ch_M= %f Max_R=%f Max_B=%f min_r=%f min_b=%f\n",ch_M[k],Max_R[k], Max_B[k],Min_R[k], Min_B[k]); + chM+=ch_M[k]; + MaxBMoy+=Max_B[k]; + MaxRMoy+=Max_R[k]; + MinRMoy+=Min_R[k]; + MinBMoy+=Min_B[k]; + + if(Max_R[k]>MaxR) MaxR=Max_R[k]; + if(Max_B[k]>MaxB) MaxB=Max_B[k]; + if(Min_R[k] MaxB) { + maxr=MaxRMoy + (MaxR-MaxRMoy)*0.66f;//#std Dev + //maxb=MinB; + maxb=MinBMoy + (MinB-MinBMoy)*0.66f; + + } + else { + maxb=MaxBMoy + (MaxB-MaxBMoy)*0.66f; + maxr=MinRMoy + (MinR-MinRMoy)*0.66f; + } + + printf("DCROP skip=%d cha=%f red=%f bl=%f \n",skip, chM,maxr,maxb); + params.dirpyrDenoise.chroma=chM/(autoNR*multip*adjustr); + params.dirpyrDenoise.redchro=maxr; + params.dirpyrDenoise.bluechro=maxb; + if(parent->adnListener) parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro); + } + if (settings->verbose) { + t2aue.set(); + printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue)); + } + + //end evaluate noise + } + // if(params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto + if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="AUT") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="AUTO")) {//reinit origCrop after Auto + PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip); + parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw ); + } + + if(params.dirpyrDenoise.Lmethod=="CUR") params.dirpyrDenoise.luma=0.5f;//very small value to init process - select curve or slider + if(params.dirpyrDenoise.Lmethod=="SLI") lldenoiseutili=false; + + if((lldenoiseutili || ccdenoiseutili ) && skip==1 && params.dirpyrDenoise.enabled) {//only allocate memory if enabled and skip calclum = new Imagefloat (cropw, croph);//for Luminance denoise curve if(origCrop != calclum) origCrop->copyData(calclum); parent->imgsrc->convertColorSpace(calclum, params.icm, parent->currWB, params.raw);//for denoise luminance curve } + if(skip!=1) if(parent->adnListener) parent->adnListener->noiseChanged(0.f, 0.f); + if (todo & M_LINDENOISE) { if (skip==1 && params.dirpyrDenoise.enabled) { + int kall=0; - parent->ipf.RGB_denoise(origCrop, origCrop, calclum, parent->imgsrc->isRAW(), /*Roffset,*/ params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve,lldenoiseutili); - } - } - // delete calclum; - + float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi; + parent->ipf.RGB_denoise(kall, trafx, trafy, trafw, trafh, widIm, heiIm, origCrop, origCrop, calclum, ch_M, max_r, max_b, parent->imgsrc->isRAW(), /*Roffset,*/ params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve,lldenoiseutili, dnNoisCCcurve,ccdenoiseutili, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi); + if(parent->adnListener) parent->adnListener->noiseChanged(nresi, highresi); + if(settings->leveldnautsimpl==1) { + if((params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PRE" && (parent->adnListener))) // force display value of sliders + parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro); + } + else { + if(params.dirpyrDenoise.C2method=="AUTO" || params.dirpyrDenoise.C2method=="PREV" && (parent->adnListener)) // force display value of sliders + parent->adnListener->chromaChanged(params.dirpyrDenoise.chroma, params.dirpyrDenoise.redchro, params.dirpyrDenoise.bluechro); + + } + + } + } parent->imgsrc->convertColorSpace(origCrop, params.icm, parent->currWB, params.raw); + delete [] ch_M; + delete [] max_r; + delete [] max_b; + delete [] min_r; + delete [] min_b; + delete [] lumL; + delete [] chromC; + delete [] ry; + delete [] sk; + delete [] pcsk; + delete [] centerTile_X; + delete [] centerTile_Y; + } // has to be called after setCropSizes! Tools prior to this point can't handle the Edit mechanism, but that shouldn't be a problem. @@ -322,7 +759,7 @@ void Crop::update (int todo) { if (!cieCrop) { cieCrop = new CieImage (cropw, croph); } - if(settings->ciecamfloat) { + if(settings->leveldnautsimpl==1) { float d; // not used after this block skip2=skip; parent->ipf.ciecam_02float (cieCrop, float(adap), begh, endh, 1, 2, labnCrop, ¶ms, parent->customColCurve1, parent->customColCurve2, parent->customColCurve3, diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index f5db76ce1..68cfb0a02 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -23,6 +23,7 @@ #include "simpleprocess.h" #include "../rtgui/ppversion.h" #include "colortemp.h" +#include "improcfun.h" namespace rtengine { @@ -32,7 +33,8 @@ ImProcCoordinator::ImProcCoordinator () : orig_prev(NULL), oprevi(NULL), oprevl(NULL), nprevl(NULL), previmg(NULL), workimg(NULL), ncie(NULL), imgsrc(NULL), shmap(NULL), lastAwbEqual(0.), ipf(¶ms, true), scale(10), highDetailPreprocessComputed(false), highDetailRawComputed(false), allocated(false), - bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(0.f), + bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(0.), chaut(0.f), redaut(0.f), blueaut(0.f), maxredaut(0.f), maxblueaut(0.f),nresi(0.f), + chromina(0.f), sigma(0.f), lumema(0.f),minredaut(0.f), minblueaut(0.f), hltonecurve(65536,0), shtonecurve(65536,2),//clip above @@ -47,6 +49,7 @@ ImProcCoordinator::ImProcCoordinator () clToningcurve(65536,0), cl2Toningcurve(65536,0), Noisecurve(65536,0), + NoiseCCcurve(65536,0), vhist16(65536),vhist16bw(65536), lhist16(65536), lhist16Cropped(65536), lhist16CAM(65536), lhist16CroppedCAM(65536), @@ -81,8 +84,8 @@ ImProcCoordinator::ImProcCoordinator () bcurvehist(256), bcurvehistCropped(256), bbeforehist(256), 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),lldenoiseutili(false), opautili(false), + plistener(NULL), imageListener(NULL), aeListener(NULL), hListener(NULL),acListener(NULL), abwListener(NULL),actListener(NULL),adnListener(NULL), + resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false),utili(false),autili(false),lldenoiseutili(false), opautili(false),ccdenoiseutili(false), butili(false),ccutili(false),cclutili(false),clcutili(false),fullw(1),fullh(1) {} @@ -124,7 +127,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { int readyphase = 0; bwAutoR = bwAutoG = bwAutoB = -9000.f; - + chaut=redaut=blueaut=maxredaut=maxblueaut=nresi=highresi=0.f; + chromina=sigma=lumema=0.f; + minredaut=minblueaut=10000.f; if (todo==CROP && ipf.needsPCVignetting()) todo |= TRANSFORM; // Change about Crop does affect TRANSFORM @@ -267,25 +272,39 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { Imagefloat *calclum ; lldenoiseutili=false; - params.dirpyrDenoise.getCurves(dnNoisCurve,lldenoiseutili); - if(lldenoiseutili && scale==1 && params.dirpyrDenoise.enabled ){//only allocate memory if enabled and scale=1 + ccdenoiseutili=false; + params.dirpyrDenoise.getCurves(dnNoisCurve,dnNoisCCcurve,lldenoiseutili, ccdenoiseutili); + int nbw=6;//nb tile W + int nbh=4;// + + float *ch_M = new float [nbw*nbh];//allocate memory + float *max_r = new float [nbw*nbh];//allocate memory + float *max_b = new float [nbw*nbh];//allocate memory + + if(params.dirpyrDenoise.Lmethod=="CUR") params.dirpyrDenoise.luma=0.5f; + if(params.dirpyrDenoise.Lmethod=="SLI") lldenoiseutili=false; + + if((lldenoiseutili || ccdenoiseutili) && params.dirpyrDenoise.enabled && (scale==1)){//only allocate memory if enabled and scale=1 calclum = new Imagefloat (pW, pH);//for Luminance denoise curve if(orig_prev != calclum) orig_prev->copyData(calclum); imgsrc->convertColorSpace(calclum, params.icm, currWB, params.raw);//claculate values after colorspace conversion } - + //always enabled to calculated auto Chroma if (todo & M_LINDENOISE) { - - if (scale==1 && params.dirpyrDenoise.enabled) { - - ipf.RGB_denoise(orig_prev, orig_prev, calclum, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve, lldenoiseutili); - - } + if (params.dirpyrDenoise.enabled && (scale==1)) { + printf("IMPROC\n"); + int kall=1; + int trafx, trafy, trafw, trafh, widIm, heiIm; + ipf.RGB_denoise(kall, trafx, trafy, trafw, trafh, widIm, heiIm, orig_prev, orig_prev, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve, lldenoiseutili, dnNoisCCcurve,ccdenoiseutili, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi); + } } // delete calclum; - + delete [] ch_M; + delete [] max_r; + delete [] max_b; + 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 79c7351bd..67f3bc737 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -84,6 +84,7 @@ class ImProcCoordinator : public StagedImageProcessor { LUTf hltonecurve; LUTf shtonecurve; LUTf tonecurve; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema; LUTf lumacurve; LUTf chroma_acurve; @@ -94,6 +95,7 @@ class ImProcCoordinator : public StagedImageProcessor { LUTf clToningcurve; LUTf cl2Toningcurve; LUTf Noisecurve; + LUTf NoiseCCcurve; LUTu vhist16,vhist16bw; LUTu lhist16,lhist16Cropped; @@ -119,12 +121,14 @@ class ImProcCoordinator : public StagedImageProcessor { bool cclutili; bool clcutili; bool lldenoiseutili; + bool ccdenoiseutili; bool opautili; ToneCurve customToneCurve1; ToneCurve customToneCurve2; ColorGradientCurve ctColorCurve; OpacityCurve ctOpacityCurve; NoisCurve dnNoisCurve; + NoisCCcurve dnNoisCCcurve; ColorAppearance customColCurve1; ColorAppearance customColCurve2; ColorAppearance customColCurve3; @@ -146,6 +150,7 @@ class ImProcCoordinator : public StagedImageProcessor { AutoCamListener* acListener; AutoBWListener* abwListener; AutoColorTonListener* actListener; + AutoChromaListener* adnListener; HistogramListener* hListener; std::vector sizeListeners; @@ -222,6 +227,7 @@ class ImProcCoordinator : public StagedImageProcessor { void setAutoCamListener (AutoCamListener* acl) {acListener = acl; } void setAutoBWListener (AutoBWListener* abw) {abwListener = abw; } void setAutoColorTonListener (AutoColorTonListener* bwct) {actListener = bwct; } + void setAutoChromaListener (AutoChromaListener* adn) {adnListener = adn; } void saveInputICCReference (const Glib::ustring& fname); diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 7fa07a5da..b2df211b1 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -178,8 +178,25 @@ class ImProcFunctions { float noisered; float noiseblue; bool perf; - + float Qhigh; double lumimul[3]; +// float chau; +// float chred; +// float chblue; +// float maxchred; +// float maxchblue; +// float minchred; +// float minchblue; +// float resid;//used by noise_residual +// float residred;//used by noise_residual +// float residblue;//used by noise_residual +// int nb; + int nbresid; + float redresid; + float blueresid; +// float maxredresid;//used by noise_residual +// float maxblueresid;//used by noise_residual + int comptlevel; static void initCache (); static void cleanupCache (); @@ -259,7 +276,11 @@ 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, Imagefloat * calclum, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp,const NoisCurve & ctNoisCurve , bool lldenoiseutili); + void Tile_calc (int tilesize, int overlap, int kall, int imwidth, int imheight, int &numtiles_W, int &numtiles_H, int &tilewidth, int &tileheight, int &tileWskip, int &tileHskip); + + void RGB_denoise(int kall, int trafx, int trafy, int trafw, int trafh, int widIm, int heiIm, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp,const NoisCurve & ctNoisCurve , bool lldenoiseutili, const NoisCCcurve & ctNoisCCcurve , bool ccdenoiseutili, float &chaut, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &nresi, float &highresi); + void RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope); + void RGB_denoise_info(Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp,const NoisCurve & ctNoisCurve , bool lldenoiseutili, const NoisCCcurve & ctNoisCCcurve , bool ccdenoiseutili, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut,float &nresi, float &highresi, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel,float &skinc, float &nsknc); 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 +288,13 @@ 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 **noisevarlum, int width, int height, float *mad_LL, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve); + wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float **noisevarlum, float **noisevarchrom, int width, int height, float *mad_LL, float *mad_aa, float *mad_bb, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve, const NoisCCcurve & dnNoisCCcurve, bool ccdenoiseutili, float &chaut, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, int schoice, bool autoch); + void WaveletDenoiseAll_info(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a, + wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float *mad_LL, float *mad_aa, float *mad_bb, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve, const NoisCCcurve & dnNoisCCcurve, bool ccdenoiseutili, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut,float &minredaut, float & minblueaut, int schoice, bool autoch, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel,float &skinc, float &nsknc, + float &maxchred, float &maxchblue,float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue); void WaveletDenoiseAll_BiShrink(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a, - 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); + wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float **noisevarlum, float **noisevarchrom, int width, int height, float *mad_LL, float *mad_aa, float *mad_bb, float noisevar_abr, float noisevar_abb, LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve, const NoisCCcurve & dnNoisCCcurve, bool ccdenoiseutili, float &chaut, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, int schoice, bool autoch); //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,9 +302,13 @@ 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 **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); + int W_L, int H_L, int W_ab, int H_ab, int skip_L, int skip_ab, float noisevar_L, float **noisevarlum, float **noisevarchrom, int width, int height, float *mad_LL, float *mad_aa, float *mad_bb, float noisevar_abr, float noisevar_abb,LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve, const NoisCCcurve & dnNoisCCcurve, bool ccdenoiseutili, float &chaut, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, int callby, bool autoch, float * madaa = NULL, float * madab = NULL, float * madaL = NULL, bool madCalculated= false); + void ShrinkAll_info(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 **noisevarlum, float **noisevarchrom, float **noisevarhue, int width, int height, float *mad_LL, float *mad_aa, float *mad_bb, float noisevar_abr, float noisevar_abb,LabImage * noi, bool lldenoiseutili, const NoisCurve & dnNoisCurve, const NoisCCcurve & dnNoisCCcurve, bool ccdenoiseutili, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int callby, bool autoch, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel,float &skinc, float &nsknc, + float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, float * madaa = NULL, float * madab = NULL, float * madaL = NULL, bool madCalculated= false); + void Noise_residual(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a, wavelet_decomposition &WaveletCoeffs_b, int width, int height, float &chresid, float &chmaxredresid,float &chmaxblueresid, float &chresidred, float & chresidblue, float resid, float residblue, float residred, float maxredresid, float maxblueresid, float nbresid); + void calcautodn_info (float &chaut, float &delta, int Nb, int levaut, float maxmax, float lumema, float chromina, int mode, int lissage, float redyel, float skinc, float nsknc); + float MadMax(float * HH_Coeffs, int &max, int datalen); float Mad(float * HH_Coeffs, int datalen, int * histo); // pyramid equalizer diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 1075d2ce6..7712a5c22 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -323,6 +323,11 @@ enum ProcEvent { EvDPDNLCurve=295, EvDPDNsmet=296, EvPreProcessDeadPixel=297, + EvDPDNCCCurve=298, + EvDPDNautochroma=299, + EvDPDNLmet=300, + EvDPDNCmet=301, + EvDPDNC2met=302, NUMOFEVENTS }; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index e1cedb572..9e8fbf335 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -428,15 +428,34 @@ void DirPyrDenoiseParams::getDefaultNoisCurve(std::vector &curve) { curve.at(i) = v[i-1]; } +void DirPyrDenoiseParams::getDefaultCCCurve(std::vector &curve) { + // double v[8]= { 0.15, 0.00,0.35,0.35, + // 0.60, 0.05,0.35,0.35}; + double v[8]= { 0.05, 0.50,0.35,0.35, + 0.35, 0.05,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); + std::vector ccCurve; + ccCurve = this->cccurve; + cccurveLUT.Set(ccCurve, ccdenoiseutili); + } @@ -1254,11 +1277,15 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol if (!pedited || pedited->dirpyrDenoise.enabled) keyFile.set_boolean ("Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled); if (!pedited || pedited->dirpyrDenoise.enhance) keyFile.set_boolean ("Directional Pyramid Denoising", "Enhance", dirpyrDenoise.enhance); if (!pedited || pedited->dirpyrDenoise.median) keyFile.set_boolean ("Directional Pyramid Denoising", "Median", dirpyrDenoise.median); + if (!pedited || pedited->dirpyrDenoise.autochroma) keyFile.set_boolean ("Directional Pyramid Denoising", "Auto", dirpyrDenoise.autochroma); // if (!pedited || pedited->dirpyrDenoise.perform) keyFile.set_boolean ("Directional Pyramid Denoising", "Perform", dirpyrDenoise.perform); if (!pedited || pedited->dirpyrDenoise.luma) keyFile.set_double ("Directional Pyramid Denoising", "Luma", dirpyrDenoise.luma); 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.Lmethod) keyFile.set_string ("Directional Pyramid Denoising", "LMethod", dirpyrDenoise.Lmethod); + if (!pedited || pedited->dirpyrDenoise.Cmethod) keyFile.set_string ("Directional Pyramid Denoising", "CMethod", dirpyrDenoise.Cmethod); + if (!pedited || pedited->dirpyrDenoise.C2method) keyFile.set_string ("Directional Pyramid Denoising", "C2Method", dirpyrDenoise.C2method); 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); @@ -1271,6 +1298,10 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol Glib::ArrayHandle lcurve = dirpyrDenoise.lcurve; keyFile.set_double_list("Directional Pyramid Denoising", "LCurve", lcurve); } + if (!pedited || pedited->dirpyrDenoise.cccurve) { + Glib::ArrayHandle cccurve = dirpyrDenoise.cccurve; + keyFile.set_double_list("Directional Pyramid Denoising", "CCCurve", cccurve); + } //Save epd. if (!pedited || pedited->epd.enabled) keyFile.set_boolean ("EPD", "Enabled", epd.enabled); @@ -1921,16 +1952,21 @@ if (keyFile.has_group ("Directional Pyramid Denoising")) {//TODO: No longer an a if (keyFile.has_key ("Directional Pyramid Denoising", "Enabled")) { dirpyrDenoise.enabled = keyFile.get_boolean ("Directional Pyramid Denoising", "Enabled"); if (pedited) pedited->dirpyrDenoise.enabled = true; } if (keyFile.has_key ("Directional Pyramid Denoising", "Enhance")) { dirpyrDenoise.enhance = keyFile.get_boolean ("Directional Pyramid Denoising", "Enhance"); if (pedited) pedited->dirpyrDenoise.enhance = true; } if (keyFile.has_key ("Directional Pyramid Denoising", "Median")) { dirpyrDenoise.median = keyFile.get_boolean ("Directional Pyramid Denoising", "Median"); if (pedited) pedited->dirpyrDenoise.median = true; } + if (keyFile.has_key ("Directional Pyramid Denoising", "Auto")) { dirpyrDenoise.autochroma = keyFile.get_boolean ("Directional Pyramid Denoising", "Auto"); if (pedited) pedited->dirpyrDenoise.autochroma = true; } // if (keyFile.has_key ("Directional Pyramid Denoising", "Perform")) { dirpyrDenoise.perform = keyFile.get_boolean ("Directional Pyramid Denoising", "Perform"); if (pedited) pedited->dirpyrDenoise.perform = true; } if (keyFile.has_key ("Directional Pyramid Denoising", "Luma")) { dirpyrDenoise.luma = keyFile.get_double ("Directional Pyramid Denoising", "Luma"); if (pedited) pedited->dirpyrDenoise.luma = true; } 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", "LMethod")) {dirpyrDenoise.Lmethod = keyFile.get_string ("Directional Pyramid Denoising", "LMethod"); if (pedited) pedited->dirpyrDenoise.Lmethod = true; } + if (keyFile.has_key ("Directional Pyramid Denoising", "CMethod")) {dirpyrDenoise.Cmethod = keyFile.get_string ("Directional Pyramid Denoising", "CMethod"); if (pedited) pedited->dirpyrDenoise.Cmethod = true; } + if (keyFile.has_key ("Directional Pyramid Denoising", "C2Method")) {dirpyrDenoise.C2method = keyFile.get_string ("Directional Pyramid Denoising", "C2Method"); if (pedited) pedited->dirpyrDenoise.C2method = 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", "CCCurve")) {dirpyrDenoise.cccurve = keyFile.get_double_list ("Directional Pyramid Denoising", "CCCurve"); if (pedited) pedited->dirpyrDenoise.cccurve = 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; } @@ -2441,12 +2477,17 @@ bool ProcParams::operator== (const ProcParams& other) { && dirpyrDenoise.enabled == other.dirpyrDenoise.enabled && dirpyrDenoise.enhance == other.dirpyrDenoise.enhance && dirpyrDenoise.median == other.dirpyrDenoise.median + && dirpyrDenoise.autochroma == other.dirpyrDenoise.autochroma // && dirpyrDenoise.perform == other.dirpyrDenoise.perform && dirpyrDenoise.luma == other.dirpyrDenoise.luma && dirpyrDenoise.lcurve == other.dirpyrDenoise.lcurve + && dirpyrDenoise.cccurve == other.dirpyrDenoise.cccurve && dirpyrDenoise.Ldetail == other.dirpyrDenoise.Ldetail && dirpyrDenoise.chroma == other.dirpyrDenoise.chroma && dirpyrDenoise.dmethod == other.dirpyrDenoise.dmethod + && dirpyrDenoise.Lmethod == other.dirpyrDenoise.Lmethod + && dirpyrDenoise.Cmethod == other.dirpyrDenoise.Cmethod + && dirpyrDenoise.C2method == other.dirpyrDenoise.C2method && dirpyrDenoise.smethod == other.dirpyrDenoise.smethod && dirpyrDenoise.medmethod == other.dirpyrDenoise.medmethod && dirpyrDenoise.methodmed == other.dirpyrDenoise.methodmed diff --git a/rtengine/procparams.h b/rtengine/procparams.h index bc630ef98..c42077091 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -33,6 +33,7 @@ namespace rtengine { class ColorGradientCurve; class OpacityCurve; class NoisCurve; +class NoisCCcurve; namespace procparams { @@ -543,10 +544,12 @@ class DirPyrDenoiseParams { public: std::vector lcurve; + std::vector cccurve; bool enabled; bool enhance; bool median; + bool autochroma; bool perform; double luma; @@ -556,6 +559,9 @@ class DirPyrDenoiseParams { double bluechro; double gamma; Glib::ustring dmethod; + Glib::ustring Lmethod; + Glib::ustring Cmethod; + Glib::ustring C2method; Glib::ustring smethod; Glib::ustring medmethod; Glib::ustring methodmed; @@ -564,9 +570,11 @@ class DirPyrDenoiseParams { DirPyrDenoiseParams (); void setDefault(); // SHOULD BE GENERALIZED TO ALL CLASSES! - void getCurves(NoisCurve &lcurveLUT, bool &lldenoiseutili) const; + // void getCurves(NoisCurve &lcurveLUT, bool &lldenoiseutili) const; + void getCurves(NoisCurve &lcurveLUT,NoisCCcurve &cccurveLUT,bool &lldenoiseutili,bool &ccdenoiseutili ) const; static void getDefaultNoisCurve(std::vector &curve); + static void getDefaultCCCurve(std::vector &curve); }; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index daa48f09a..0542e4356 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -319,7 +319,12 @@ RGBCURVE, //EvFilmSimulationStrength RGBCURVE, //EvFilmSimulationFilename ALLNORAW, // EvDPDNLCurve ALLNORAW, // EvDPDNsmet -DARKFRAME // EvPreProcessDeadPixel +DARKFRAME, // EvPreProcessDeadPixel +ALLNORAW, //EvDPDNCCCurve +ALLNORAW, //EvDPDNautochroma +ALLNORAW, // EvDPDNLmet +ALLNORAW, // EvDPDNCmet +ALLNORAW // EvDPDNC2met }; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index eab0cd0a9..b78a744fb 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -209,6 +209,8 @@ namespace rtengine { virtual void setDetailedCrop (IImage8* img, IImage8* imgtrue, procparams::ColorManagementParams cmp, procparams::CropParams cp, int cx, int cy, int cw, int ch, int skip) {} virtual bool getWindow (int& cx, int& cy, int& cw, int& ch, int& skip) { return false; } + // virtual void setPosition (int x, int y, bool update=true) {} + }; /** This listener is used when the full size of the final image has been changed (e.g. rotated by 90 deg.) */ @@ -258,6 +260,15 @@ namespace rtengine { virtual void autoCamChanged (double ccam) {} virtual void adapCamChanged (double cadap) {} }; + + class AutoChromaListener { + public : + virtual ~AutoChromaListener() {} + virtual void chromaChanged (double autchroma, double autred, double autblue) {} + virtual void noiseChanged (double nresid, double highresid) {} + virtual void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP) {} + + }; class AutoColorTonListener { public : @@ -361,6 +372,7 @@ namespace rtengine { virtual void setAutoCamListener (AutoCamListener* l) =0; virtual void setAutoBWListener (AutoBWListener* l) =0; virtual void setAutoColorTonListener (AutoColorTonListener* l) =0; + virtual void setAutoChromaListener (AutoChromaListener* l) =0; virtual ~StagedImageProcessor () {} diff --git a/rtengine/settings.h b/rtengine/settings.h index 64abb47a4..ddb30b726 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -29,6 +29,11 @@ namespace rtengine { int viewingdevice; // white of output device (D50...D65..) int viewingdevicegrey; // level of grey output device int viewinggreySc; // level of grey Scene + int leveldnv; // level of crop denoise + int leveldnti; // size of tiles denoise + int leveldnaut; // level of auto denoise + int leveldnliss; // level of auto multi zone + int leveldnautsimpl; // STD or EXPERT Glib::ustring monitorProfile; ///< ICC profile of the monitor (full path recommended) bool autoMonitorProfile; ///< Try to auto-determine the correct monitor color profile @@ -55,6 +60,11 @@ namespace rtengine { int amchroma; int protectred; double protectredh; + double nrauto; + double nrautomax; + double nrhigh; + int nrwavlevel; + bool ciebadpixgauss; int CRI_color; // N� for display Lab value ; 0 disabled int denoiselabgamma; // 0=gamma 26 11 1=gamma 40 5 2 =gamma 55 10 diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 7719c0bff..f907cd6b7 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -29,8 +29,8 @@ #include "rawimagesource.h" #include "../rtgui/ppversion.h" #include "../rtgui/multilangmgr.h" -//#include "mytime.h" - +#include "mytime.h" +#include "StopWatch.h" #undef THREAD_PRIORITY_NORMAL #ifdef _OPENMP #include @@ -124,6 +124,389 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p imgsrc->getAutoWBMultipliers(rm, gm, bm); currWB.update(rm, gm, bm, params.wb.equal); } + + NoisCurve dnNoisCurve; + bool lldenoiseutili=false; + bool ccdenoiseutili=false; + NoisCCcurve dnNoisCCcurve; + Imagefloat *calclum ; + params.dirpyrDenoise.getCurves(dnNoisCurve, dnNoisCCcurve, lldenoiseutili, ccdenoiseutili); + float autoNR = (float) settings->nrauto;// + float autoNRmax = (float) settings->nrautomax;// + float autohigh = (float) settings->nrhigh;// + int tilesize; + int overlap; + if(settings->leveldnti ==0) { + tilesize = 1024; + overlap = 128; + } + if(settings->leveldnti ==1) { + tilesize = 768; + overlap = 96; + } + + // const int tilesize = 768; + // const int overlap = 96; + int numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip; + ipf.Tile_calc (tilesize, overlap, 2, fw, fh, numtiles_W, numtiles_H, tilewidth, tileheight, tileWskip, tileHskip); + int nbtl=numtiles_W*numtiles_H; + if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="AUT") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="AUTO")) nbtl=9; + float *ch_M = new float [nbtl];//allocate memory + float *max_r = new float [nbtl]; + float *max_b = new float [nbtl]; + float *min_b = new float [9]; + float *min_r = new float [9]; + float *lumL = new float [nbtl]; + float *chromC = new float [nbtl]; + float *ry = new float [nbtl]; + float *sk = new float [nbtl]; + float *pcsk = new float [nbtl]; + float *Max_R_ =new float [nbtl]; + float *Max_B_ = new float [nbtl]; + float *Min_R_ =new float [nbtl]; + float *Min_B_ = new float [nbtl]; + float *delta_ = new float [nbtl]; + // printf("expert=%d\n",settings->leveldnautsimpl); + if(settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="PON") { + MyTime t1pone,t2pone; + t1pone.set(); + int crW,crH; + if(settings->leveldnv ==0) {crW=100;crH=100;} + if(settings->leveldnv ==1) {crW=250;crH=250;} + if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(tileHskip/2);} + // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview + if(settings->leveldnv ==3) {crW=tileWskip-10;crH=tileHskip-10;} + + float lowdenoise=1.f; + int levaut=settings->leveldnaut; + if(levaut==1) //Standard + lowdenoise=0.7f; + + // int crW=tileWskip-10;//crop noise width + // int crH=tileHskip-10;//crop noise height + Imagefloat *origCropPart;//init auto noise + origCropPart = new Imagefloat (crW, crH);//allocate memory + StopWatch Stop1("denoise info tiled"); + if (params.dirpyrDenoise.enabled) {//evaluate Noise + LUTf gamcurve(65536,0); + float gam, gamthresh, gamslope; + ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); + #pragma omp parallel + { + Imagefloat *origCropPart;//init auto noise + origCropPart = new Imagefloat (crW, crH);//allocate memory + Imagefloat *provi; + Imagefloat *provicalc; + provi = new Imagefloat (crW, crH); + provicalc = new Imagefloat (crW, crH); + int skipP=1; + #pragma omp for schedule(dynamic) collapse(2) nowait + for(int wcr=0;wcrgetImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw ); + if(origCropPart != provi) + origCropPart->copyData(provi); + if(origCropPart != provicalc) + origCropPart->copyData(provicalc); + imgsrc->convertColorSpace(provicalc, params.icm, currWB, params.raw);//for denoise luminance curve + float maxr=0.f; + float maxb=0.f; + float pondcorrec=1.0f; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + int Nb; + chaut=0.f;redaut=0.f; blueaut=0.f; maxredaut=0.f; maxblueaut=0.f;chromina=0.f; sigma=0.f; + ipf.RGB_denoise_info(provi, provi, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve,lldenoiseutili, dnNoisCCcurve,ccdenoiseutili, chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + float multip=1.f; + float adjustr=1.f; + if (params.icm.working=="ProPhoto") {adjustr =1.f;}// + else if (params.icm.working=="Adobe RGB") {adjustr = 1.f/1.3f;} + else if (params.icm.working=="sRGB") {adjustr = 1.f/1.3f;} + else if (params.icm.working=="WideGamut") {adjustr =1.f/1.1f;} + else if (params.icm.working=="Beta RGB") {adjustr =1.f/1.2f;} + else if (params.icm.working=="BestRGB") {adjustr =1.f/1.2f;} + else if (params.icm.working=="BruceRGB") {adjustr =1.f/1.2f;} + + if(!imgsrc->isRAW()) multip=2.f;//take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + float maxmax=max(maxredaut,maxblueaut); + float delta; + int mode=2; + int lissage=settings->leveldnliss; + ipf.calcautodn_info (chaut, delta, Nb, levaut, maxmax, lumema, chromina, mode, lissage, redyel, skinc, nsknc); + + // printf("PROCESS cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f sigL=%f\n",chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema, sigma_L); + if(maxredaut > maxblueaut) { + maxr=(delta)/((autoNRmax*multip*adjustr*lowdenoise)/2.f); + if(minblueaut <= minredaut && minblueaut < chaut) maxb=(-chaut+minblueaut)/(autoNRmax*multip*adjustr*lowdenoise); + } + else { + maxb=(delta)/((autoNRmax*multip*adjustr*lowdenoise)/2.f); + if(minredaut <= minblueaut && minredaut < chaut) maxr=(-chaut+minredaut)/(autoNRmax*multip*adjustr*lowdenoise); + }//maxb mxr - empirical evaluation red / blue + + ch_M[hcr*numtiles_W + wcr]=pondcorrec*chaut/(autoNR*multip*adjustr*lowdenoise); + max_r[hcr*numtiles_W + wcr]=pondcorrec*maxr; + max_b[hcr*numtiles_W + wcr]=pondcorrec*maxb; + lumL[hcr*numtiles_W + wcr]=lumema; + chromC[hcr*numtiles_W + wcr]=chromina; + ry[hcr*numtiles_W + wcr]=redyel; + sk[hcr*numtiles_W + wcr]=skinc; + pcsk[hcr*numtiles_W + wcr]=nsknc; + + } + } + + delete provicalc; + delete provi; + delete origCropPart; + } + + int liss=settings->leveldnliss;//smooth result around mean + + if(liss==2 || liss==3){ + // I smooth only mean and not delta (max) + float nchm=0.f; + float koef=0.4f;//between 0.1 to 0.9 + if(liss==3) koef=0.0f;//quasi auto for mean Ch + for(int wcr=0;wcrMaxR) MaxR=Max_R_[k]; + if(max_b[k]>MaxB) MaxB=Max_B_[k]; + + } + MaxBMoy/=nbtl; + MaxRMoy/=nbtl; + + for(int k=0;k MaxB) { + max_r[k]=MaxRMoy + (MaxR-MaxRMoy)*0.66f;//#std Dev + //max_b[k]=MinB; + max_b[k]=MaxBMoy + (MaxB-MaxBMoy)*0.66f; + + } + else { + max_b[k]=MaxBMoy + (MaxB-MaxBMoy)*0.66f; + //max_r[k]=MinR; + max_r[k]=MaxRMoy + (MaxR-MaxRMoy)*0.66f; + + } + } + } + + if (settings->verbose) { + t2pone.set(); + printf("Info denoise ponderated performed in %d usec:\n", t2pone.etime(t1pone)); + } + + } + Stop1.stop(); + } + + + if((settings->leveldnautsimpl==1 && params.dirpyrDenoise.Cmethod=="AUT") || (settings->leveldnautsimpl==0 && params.dirpyrDenoise.C2method=="AUTO")) { + MyTime t1aue,t2aue; + t1aue.set(); + int crW,crH; + if(settings->leveldnv ==0) {crW=100;crH=100;} + if(settings->leveldnv ==1) {crW=250;crH=250;} + if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(tileHskip/2);} + // if(settings->leveldnv ==2) {crW=int(tileWskip/2);crH=int(1.15f*(tileWskip/2));}//adapted to scale of preview + if(settings->leveldnv ==3) {crW=tileWskip-10;crH=tileHskip-10;} + + float lowdenoise=1.f; + int levaut=settings->leveldnaut; + if(levaut==1) //Standard + lowdenoise=0.7f; + + if (params.dirpyrDenoise.enabled) {//evaluate Noise + LUTf gamcurve(65536,0); + float gam, gamthresh, gamslope; + ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); + int Nb; + #pragma omp parallel + { + Imagefloat *origCropPart;//init auto noise + origCropPart = new Imagefloat (crW, crH);//allocate memory + Imagefloat *provi; + Imagefloat *provicalc; + provi = new Imagefloat (crW, crH); + provicalc = new Imagefloat (crW, crH); + int coordW[3];//coordonate of part of image to mesure noise + int coordH[3]; + int begW=50; + int begH=50; + coordW[0]=begW;coordW[1]=fw/2-crW/2;coordW[2]=fw-crW-begW; + coordH[0]=begH;coordH[1]=fh/2-crH/2;coordH[2]=fh-crH-begH; + + #pragma omp for schedule(dynamic) collapse(2) nowait + for(int wcr=0;wcr<=2;wcr++) { + for(int hcr=0;hcr<=2;hcr++) { + + PreviewProps ppP (coordW[wcr] , coordH[hcr], crW, crH, 1); + + imgsrc->getImage (currWB, tr, origCropPart, ppP, params.toneCurve, params.icm, params.raw); + + if(origCropPart != provi) + origCropPart->copyData(provi); + if(origCropPart != provicalc) + origCropPart->copyData(provicalc); + imgsrc->convertColorSpace(provicalc, params.icm, currWB, params.raw);//for denoise luminance curve + float maxr=0.f; + float maxb=0.f; + float pondcorrec=1.0f; + + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + chaut=0.f;redaut=0.f; blueaut=0.f; maxredaut=0.f; maxblueaut=0.f;chromina=0.f; sigma=0.f;sigma_L=0.f; + ipf.RGB_denoise_info(provi, provi, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise,params.defringe, imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve,lldenoiseutili, dnNoisCCcurve,ccdenoiseutili, chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + + ch_M[hcr*3 + wcr]=pondcorrec*chaut; + max_r[hcr*3 + wcr]=pondcorrec*maxredaut; + max_b[hcr*3 + wcr]=pondcorrec*maxblueaut; + min_r[hcr*3 + wcr]=pondcorrec*minredaut; + min_b[hcr*3 + wcr]=pondcorrec*minblueaut; + lumL[hcr*3 + wcr]=lumema; + chromC[hcr*3 + wcr]=chromina; + ry[hcr*3 + wcr]=redyel; + sk[hcr*3 + wcr]=skinc; + pcsk[hcr*3 + wcr]=nsknc; + + } + } + delete provicalc; + delete provi; + delete origCropPart; + } + float chM=0.f; + float MaxR=0.f; + float MaxB=0.f; + float MinR=100000000.f; + float MinB=100000000.f; + float maxr=0.f; + float maxb=0.f; + float multip=1.f; + float adjustr=1.f; + float Max_R[9]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f}; + float Max_B[9]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f}; + float Min_R[9]; + float Min_B[9]; + float MaxRMoy=0.f; + float MaxBMoy=0.f; + float MinRMoy=0.f; + float MinBMoy=0.f; + + if (params.icm.working=="ProPhoto") {adjustr =1.f;} + else if (params.icm.working=="Adobe RGB") {adjustr = 1.f/1.3f;} + else if (params.icm.working=="sRGB") {adjustr = 1.f/1.3f;} + else if (params.icm.working=="WideGamut") {adjustr =1.f/1.1f;} + else if (params.icm.working=="Beta RGB") {adjustr =1.f/1.2f;} + else if (params.icm.working=="BestRGB") {adjustr =1.f/1.2f;} + else if (params.icm.working=="BruceRGB") {adjustr =1.f/1.2f;} + + if(!imgsrc->isRAW()) multip=2.f;//take into account gamma for TIF / JPG approximate value...not good fot gamma=1 + + float maxmax; + float minmin; + float delta[9]; + int mode=1; + int lissage=settings->leveldnliss; + float redyel, skinc, nsknc; + for(int k=0;k<9;k++) { + maxmax=max(max_r[k],max_b[k]); + ipf.calcautodn_info (ch_M[k], delta[k], Nb, levaut, maxmax, lumL[k], chromC[k], mode, lissage,ry[k], sk[k], pcsk[k] ); + // printf("ch_M=%f delta=%f\n",ch_M[k], delta[k]); + } + for(int k=0;k<9;k++) { + if(max_r[k] > max_b[k]) { + minmin=min(min_r[k],min_b[k]); + //printf("R delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise); + Max_R[k]=(delta[k])/((autoNRmax*multip*adjustr*lowdenoise)/2.f); + Min_B[k]= -(ch_M[k]-min_b[k])/(autoNRmax*multip*adjustr*lowdenoise); + Max_B[k]=0.f; + Min_R[k]=0.f; + } + else { + minmin=min(min_r[k],min_b[k]); + //printf("B delta=%f koef=%f\n",delta[k],autoNRmax*multip*adjustr*lowdenoise); + Max_B[k]=(delta[k])/((autoNRmax*multip*adjustr*lowdenoise)/2.f); + Min_R[k]=- (ch_M[k]-min_r[k]) / (autoNRmax*multip*adjustr*lowdenoise); + Min_B[k]=0.f; + Max_R[k]=0.f; + } + } + + for(int k=0;k<9;k++) { + // printf("ch_M= %f Max_R=%f Max_B=%f min_r=%f min_b=%f\n",ch_M[k],Max_R[k], Max_B[k],Min_R[k], Min_B[k]); + chM+=ch_M[k]; + MaxBMoy+=Max_B[k]; + MaxRMoy+=Max_R[k]; + MinRMoy+=Min_R[k]; + MinBMoy+=Min_B[k]; + if(Max_R[k]>MaxR) MaxR=Max_R[k]; + if(Max_B[k]>MaxB) MaxB=Max_B[k]; + if(Min_R[k] MaxB) { + maxr=MaxRMoy + (MaxR-MaxRMoy)*0.66f;//#std Dev + // maxb=MinB; + maxb=MinBMoy + (MinB-MinBMoy)*0.66f; + + } + else { + maxb=MaxBMoy + (MaxB-MaxBMoy)*0.66f; + // maxr=MinR; + maxr=MinRMoy + (MinR-MinRMoy)*0.66f; + + } + + printf("SIMPL cha=%f red=%f bl=%f \n",chM,maxr,maxb); + + params.dirpyrDenoise.chroma=chM/(autoNR*multip*adjustr); + params.dirpyrDenoise.redchro=maxr; + params.dirpyrDenoise.bluechro=maxb; + } + if (settings->verbose) { + t2aue.set(); + printf("Info denoise auto performed in %d usec:\n", t2aue.etime(t1aue)); + } + + //end evaluate noise + } + + + + + Imagefloat* baseImg = new Imagefloat (fw, fh); imgsrc->getImage (currWB, tr, baseImg, pp, params.toneCurve, params.icm, params.raw); if (pl) pl->setProgress (0.45); @@ -153,11 +536,16 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p // perform luma/chroma denoise // CieImage *cieView; - NoisCurve dnNoisCurve; - bool lldenoiseutili=false; - Imagefloat *calclum ; - params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoiseutili); - if (params.dirpyrDenoise.enabled && lldenoiseutili) { +// NoisCurve dnNoisCurve; +// bool lldenoiseutili=false; +// Imagefloat *calclum ; +// params.dirpyrDenoise.getCurves(dnNoisCurve, lldenoiseutili); +// if (params.dirpyrDenoise.enabled && lldenoiseutili) { + if(params.dirpyrDenoise.Lmethod=="CUR") params.dirpyrDenoise.luma=0.5f; + if(params.dirpyrDenoise.Lmethod=="SLI") lldenoiseutili=false; + + if (params.dirpyrDenoise.enabled && (lldenoiseutili || ccdenoiseutili )) { + calclum = new Imagefloat (fw, fh);//for luminance denoise curve if(baseImg != calclum) baseImg->copyData(calclum); @@ -166,9 +554,30 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p if (params.dirpyrDenoise.enabled) { // 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); - } +// ipf.RGB_denoise(baseImg, baseImg, calclum, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve, lldenoiseutili); + float chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + int kall=2; + int trafx, trafy, trafw, trafh, widIm, heiIm; + ipf.RGB_denoise(kall, trafx, trafy, trafw, trafh, widIm, heiIm, baseImg, baseImg, calclum, ch_M, max_r, max_b, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp(), dnNoisCurve, lldenoiseutili, dnNoisCCcurve,ccdenoiseutili, chaut, redaut, blueaut, maxredaut, maxblueaut, nresi, highresi); + + } // delete calclum; + delete [] ch_M; + delete [] max_r; + delete [] max_b; + delete [] min_r; + delete [] min_b; + delete [] lumL; + delete [] chromC; + delete [] ry; + delete [] sk; + delete [] pcsk; + delete [] Max_R_; + delete [] Max_B_; + delete [] Min_R_; + delete [] Min_B_; + delete [] delta_; + imgsrc->convertColorSpace(baseImg, params.icm, currWB, params.raw); // perform first analysis diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 9689d023d..805446ea0 100755 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -1653,7 +1653,7 @@ void CropWindow::imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) { cropHandler.getPosition (cropX, cropY); phyx = (imgx - cropX)*zoomSteps[cropZoom].zoom + xpos + imgX; phyy = (imgy - cropY)*zoomSteps[cropZoom].zoom + ypos + imgY; - //printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); + // printf("imgx:%d / imgy:%d / cropX:%d / cropY:%d / xpos:%d / ypos:%d / imgX:%d / imgY:%d / leftBorder: %d / upperBorder:%d / phyx:%d / phyy:%d\n", imgx, imgy, cropX, cropY, xpos, ypos, imgX, imgY, crop->getLeftBorder(), crop->getUpperBorder(), phyx, phyy); } void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) { diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index 08449ab70..833005608 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -20,12 +20,20 @@ #include #include #include "edit.h" +#include "guiutils.h" using namespace rtengine; using namespace rtengine::procparams; +extern Options options; DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { std::vector milestones; + CurveListener::setMulti(true); + nextnresid=0.; + nexthighresid=0.; + nextchroma=15.; + nextred=0.; + nextblue=0.; enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED"))); enabled->set_tooltip_text (M("TP_DIRPYRDENOISE_ENABLED_TOOLTIP")); @@ -39,15 +47,31 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { pack_start (*hsep1); enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::enabledChanged) ); - - - luma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LUMA"), 0, 100, 0.01, 0)); - Ldetail = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LDETAIL"), 0, 100, 0.01, 50)); - 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; + Gtk::Frame* lumaFrame = Gtk::manage (new Gtk::Frame (M("TP_DIRPYRDENOISE_LUMAFR")) ); + lumaFrame->set_tooltip_text(M("TP_DIRPYRDENOISE_LUMAFR_TOOLTIP")); + lumaFrame->set_border_width(0); + lumaFrame->set_label_align(0.025, 0.5); + + Gtk::VBox * lumaVBox = Gtk::manage ( new Gtk::VBox()); + lumaVBox->set_border_width(4); + lumaVBox->set_spacing(2); + + + + ctboxL = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labmL = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_LTYPE")+":")); + ctboxL->pack_start (*labmL, Gtk::PACK_SHRINK, 1); + + Lmethod = Gtk::manage (new MyComboBoxText ()); + Lmethod->append_text (M("TP_DIRPYRDENOISE_CUR")); + Lmethod->append_text (M("TP_DIRPYRDENOISE_SLI")); + Lmethod->set_active(0); + Lmethodconn = Lmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::LmethodChanged) ); + + luma = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LUMA"), 0, 100, 0.01, 0)); + Ldetail = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_LDETAIL"), 0, 100, 0.01, 50)); NoiscurveEditorG = new CurveEditorGroup (options.lastDenoiseCurvesDir, M("TP_DIRPYRDENOISE_LCURVE")); //curveEditorG = new CurveEditorGroup (options.lastLabCurvesDir); NoiscurveEditorG->setCurveListener (this); @@ -58,31 +82,79 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { lshape->setTooltip(M("TP_DIRPYRDENOISE_CURVEEDITOR_L_TOOLTIP")); //lshape->setEditID(EUID_Lab_LCurve, BT_SINGLEPLANE_FLOAT); + 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(); + NoiscurveEditorG->show(); + Gtk::Frame* chromaFrame = Gtk::manage (new Gtk::Frame (M("TP_DIRPYRDENOISE_CHROMAFR")) ); + chromaFrame->set_border_width(0); + chromaFrame->set_label_align(0.025, 0.5); + + Gtk::VBox *chromaVBox = Gtk::manage ( new Gtk::VBox()); + chromaVBox->set_spacing(2); + chromaVBox->set_border_width(4); + + autochroma=Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_AUTO"))); + autochroma->set_active (true); + autochroma->set_tooltip_text (M("TP_DIRPYRDENOISE_AUTO_TOOLTIP")); + + ctboxC = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labmC = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_CTYPE")+":")); + ctboxC->pack_start (*labmC, Gtk::PACK_SHRINK, 1); + ctboxC->set_tooltip_markup (M("TP_DIRPYRDENOISE_CTYPE_TOOLTIP")); + + Cmethod = Gtk::manage (new MyComboBoxText ()); + Cmethod->append_text (M("TP_DIRPYRDENOISE_MAN")); + Cmethod->append_text (M("TP_DIRPYRDENOISE_AUT")); + Cmethod->append_text (M("TP_DIRPYRDENOISE_PON")); + Cmethod->append_text (M("TP_DIRPYRDENOISE_PRE")); + Cmethod->set_active(0); + Cmethodconn = Cmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::CmethodChanged) ); + + ctboxC2 = Gtk::manage (new Gtk::HBox ()); + Gtk::Label* labmC2 = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_CTYPE")+":")); + ctboxC2->pack_start (*labmC2, Gtk::PACK_SHRINK, 1); + ctboxC2->set_tooltip_markup (M("TP_DIRPYRDENOISE_C2TYPE_TOOLTIP")); + + C2method = Gtk::manage (new MyComboBoxText ()); + C2method->append_text (M("TP_DIRPYRDENOISE_MANU")); + C2method->append_text (M("TP_DIRPYRDENOISE_AUTO")); + C2method->append_text (M("TP_DIRPYRDENOISE_PREV")); + C2method->set_active(0); + C2methodconn = C2method->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::C2methodChanged) ); + + + NoiseLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); + NoiseLabels->set_tooltip_text(M("TP_DIRPYRDENOISE_NRESID_TOOLTIP")); + + TileLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); + PrevLabels = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER)); + + 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)); 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")); - passes = Gtk::manage (new Adjuster (M("TP_DIRPYRDENOISE_PASSES"), 1.0, 3.0, 1., 1.)); - passes->set_tooltip_text (M("TP_DIRPYRDENOISE_PASSES_TOOLTIP")); - Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ()); hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_DIRPYRDENOISE_METHOD") +": ")),Gtk::PACK_SHRINK, 4); hb1->set_tooltip_markup (M("TP_DIRPYRDENOISE_METHOD_TOOLTIP")); dmethod = Gtk::manage (new MyComboBoxText ()); - dmethod->append_text (M("TP_DIRPYRDENOISE_RGB")); dmethod->append_text (M("TP_DIRPYRDENOISE_LAB")); + dmethod->append_text (M("TP_DIRPYRDENOISE_RGB")); dmethod->set_active(0); hb1->pack_end (*dmethod, Gtk::PACK_EXPAND_WIDGET, 4); pack_start( *hb1, Gtk::PACK_SHRINK, 4); - -// perform = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_PERF"))); -// perform->set_tooltip_text (M("TP_DIRPYRDENOISE_PERF_TOOLTIP")); -// perfconn = perform->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::perform_toggled) ); dmethodconn = dmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::dmethodChanged) ); luma->setAdjusterListener (this); @@ -91,12 +163,30 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { redchro->setAdjusterListener (this); bluechro->setAdjusterListener (this); - gamma->setAdjusterListener (this); - - luma->show(); - Ldetail->show(); + CCcurveEditorG = new CurveEditorGroup (options.lastDenoiseCurvesDir, M("TP_DIRPYRDENOISE_CCCURVE")); + CCcurveEditorG->setCurveListener (this); + rtengine::DirPyrDenoiseParams::getDefaultCCCurve(defaultCurve); + ccshape = static_cast(CCcurveEditorG->addCurve(CT_Flat, "", NULL, false)); + ccshape->setIdentityValue(0.); + ccshape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + + ccshape->setTooltip(M("TP_DIRPYRDENOISE_CURVEEDITOR_CC_TOOLTIP")); + ccshape->setBottomBarColorProvider(this, 2); + + CCcurveEditorG->curveListComplete(); + //----------------------------------------- + + gamma->setAdjusterListener (this); + + luma->hide(); + Ldetail->show(); + +// autochroma->show(); + NoiseLabels->show(); + TileLabels->show(); + PrevLabels->show(); chroma->show(); redchro->show(); bluechro->show(); @@ -107,10 +197,20 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { enhance = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_ENH"))); enhance->set_active (false); enhance->set_tooltip_text (M("TP_DIRPYRDENOISE_ENH_TOOLTIP")); + // ---- Median FIltering ---- - median = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_MED"))); + Gtk::Frame* medianFrame = Gtk::manage (new Gtk::Frame ()); + medianFrame->set_border_width(0); + medianFrame->set_label_align(0.025, 0.5); + + Gtk::VBox *medianVBox = Gtk::manage ( new Gtk::VBox()); + medianVBox->set_spacing(2); + medianVBox->set_border_width(4); + + median = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_MED")+":")); median->set_active (true); median->set_tooltip_text (M("TP_DIRPYRDENOISE_MED_TOOLTIP")); + medianFrame->set_label_widget(*median); Gtk::HSeparator *hsep2 = Gtk::manage (new Gtk::HSeparator()); @@ -118,6 +218,8 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { methodmed = Gtk::manage (new MyComboBoxText ()); methodmed->append_text (M("TP_DIRPYRDENOISE_LM")); + methodmed->append_text (M("TP_DIRPYRDENOISE_ABM")); + methodmed->append_text (M("TP_DIRPYRDENOISE_LPLABM")); methodmed->append_text (M("TP_DIRPYRDENOISE_LABM")); methodmed->append_text (M("TP_DIRPYRDENOISE_RGBM")); methodmed->set_active (0); @@ -139,30 +241,23 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { medmethod->append_text (M("TP_DIRPYRDENOISE_55SOFT")); medmethod->append_text (M("TP_DIRPYRDENOISE_55")); medmethod->append_text (M("TP_DIRPYRDENOISE_77")); + medmethod->append_text (M("TP_DIRPYRDENOISE_99")); medmethod->set_active (0); medmethod->set_tooltip_text (M("TP_DIRPYRDENOISE_MET_TOOLTIP")); medmethodconn = medmethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrDenoise::medmethodChanged) ); ctboxm = Gtk::manage (new Gtk::HBox ()); - Gtk::Label* labmm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDMETHOD"))); + Gtk::Label* labmm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDMETHOD")+":")); 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"))); + Gtk::Label* labm = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDTYPE")+":")); 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"))); + Gtk::Label* labrgb = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_MEDTYPE")+":")); 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 (); @@ -170,7 +265,7 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { 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")); @@ -179,48 +274,204 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this), lastenhance(false) { // 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); + 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_PASSES"), 1.0, 3.0, 1., 1.)); passes->set_tooltip_text (M("TP_DIRPYRDENOISE_PASSES_TOOLTIP")); passes->setAdjusterListener (this); passes->show(); + ctboxL->pack_start (*Lmethod); + lumaVBox->pack_start (*ctboxL); + lumaVBox->pack_start (*luma); + lumaVBox->pack_start (*NoiscurveEditorG, Gtk::PACK_SHRINK, 4); + lumaVBox->pack_start (*Ldetail); + lumaFrame->add(*lumaVBox); + pack_start (*lumaFrame); + + ctboxC->pack_start (*Cmethod); + ctboxC2->pack_start (*C2method); + if(options.rtSettings.leveldnautsimpl==1){ + chromaVBox->pack_start (*ctboxC); + } + else { + chromaVBox->pack_start (*ctboxC2); + } + chromaVBox->pack_start (*NoiseLabels); + chromaVBox->pack_start (*TileLabels); + chromaVBox->pack_start (*PrevLabels); - pack_start (*luma); - pack_start (*NoiscurveEditorG, Gtk::PACK_SHRINK, 4); - pack_start (*Ldetail); - pack_start (*chroma); - pack_start (*redchro); - pack_start (*bluechro); - + chromaVBox->pack_start (*chroma); + chromaVBox->pack_start (*redchro); + chromaVBox->pack_start (*bluechro); + chromaVBox->pack_start (*CCcurveEditorG, Gtk::PACK_SHRINK, 4); + chromaFrame->add(*chromaVBox); + pack_start (*chromaFrame); + + pack_start (*gamma); //pack_start (*enhance); pack_start (*hsep4); - pack_start( *hb11, Gtk::PACK_SHRINK, 4); +// pack_start( *hb11, Gtk::PACK_SHRINK, 4); - pack_start (*hsep2); - pack_start (*median); +// pack_start (*hsep2); +// pack_start (*median); ctboxm->pack_start (*methodmed); ctbox->pack_start (*medmethod); ctboxrgb->pack_start (*rgbmethod); - pack_start (*ctboxm); - pack_start (*ctbox); - pack_start (*ctboxrgb); - pack_start (*passes,Gtk::PACK_SHRINK, 1); +// pack_start (*ctboxm); +// pack_start (*ctbox); +// pack_start (*ctboxrgb); +// pack_start (*passes,Gtk::PACK_SHRINK, 1); + medianVBox->pack_start (*ctboxm); + medianVBox->pack_start (*ctbox); + medianVBox->pack_start (*ctboxrgb); + medianVBox->pack_start (*passes); + medianFrame->add(*medianVBox); + + pack_start (*medianFrame); // pack_start (*perform); enhanConn = enhance->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::enhanceChanged) ); + autochromaConn = autochroma->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::autochromaChanged) ); medianConn = median->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::medianChanged) ); ctboxrgb->hide(); + } DirPyrDenoise::~DirPyrDenoise () { delete NoiscurveEditorG; + delete CCcurveEditorG; + +} +int chromaChangedUI (void* data) { + GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + (static_cast(data))->chromaComputed_ (); + return 0; +} +void DirPyrDenoise::chromaChanged (double autchroma, double autred, double autblue) +{ + nextchroma = autchroma; +// printf("CHROM=%f\n",nextchroma); + nextred=autred; + nextblue=autblue; + g_idle_add (chromaChangedUI, this); +} + +bool DirPyrDenoise::chromaComputed_ () { + + disableListener (); + chroma->setValue (nextchroma); + redchro->setValue (nextred); + bluechro->setValue (nextblue); + enableListener (); + updateNoiseLabel (); + return false; +} +int TilePrevChangedUI (void* data) { + GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + (static_cast(data))->TilePrevComputed_ (); + return 0; +} + + +void DirPyrDenoise::noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP) +{ + nexttileX=tileX; + nexttileY=tileY; + nextprevX=prevX; + nextprevY=prevY; + nextsizeT=sizeT; + nextsizeP=sizeP; + + g_idle_add (TilePrevChangedUI, this); + + +} +bool DirPyrDenoise::TilePrevComputed_ () { + + disableListener (); + enableListener (); + updateTileLabel (); + updatePrevLabel (); + return false; +} +void DirPyrDenoise::updateTileLabel () { + if (!batchMode) { + float sT; + float nX, nY; + sT=nextsizeT; + nX = nexttileX; + nY = nexttileY; + { + TileLabels->set_text( + Glib::ustring::compose(M("TP_DIRPYRDENOISE_TILELABEL"), + Glib::ustring::format(std::fixed, std::setprecision(0), sT), + Glib::ustring::format(std::fixed, std::setprecision(0), nX), + Glib::ustring::format(std::fixed, std::setprecision(0), nY)) + ); + } + } +} +void DirPyrDenoise::updatePrevLabel () { + if (!batchMode) { + float sP; + float pX, pY; + sP=nextsizeP; + pX = nextprevX; + pY = nextprevY; + { + PrevLabels->set_text( + Glib::ustring::compose(M("TP_DIRPYRDENOISE_PREVLABEL"), + Glib::ustring::format(std::fixed, std::setprecision(0), sP), + Glib::ustring::format(std::fixed, std::setprecision(0), pX), + Glib::ustring::format(std::fixed, std::setprecision(0), pY)) + ); + } + } +} + + +int noiseChangedUI (void* data) { + GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected + (static_cast(data))->noiseComputed_ (); + return 0; +} + + +void DirPyrDenoise::noiseChanged (double nresid, double highresid) +{ + nextnresid=nresid; + nexthighresid=highresid; + g_idle_add (noiseChangedUI, this); +} + +bool DirPyrDenoise::noiseComputed_ () { + + disableListener (); + enableListener (); + updateNoiseLabel (); + return false; +} + +void DirPyrDenoise::updateNoiseLabel () { + if (!batchMode) { + float nois, high; + nois = nextnresid; + high= nexthighresid; + if(nois==0.f && high==0.f) NoiseLabels->set_text(M("TP_DIRPYRDENOISE_NOISELABELEMPTY")); + else { + NoiseLabels->set_text( + Glib::ustring::compose(M("TP_DIRPYRDENOISE_NOISELABEL"), + Glib::ustring::format(std::fixed, std::setprecision(0), nois), + Glib::ustring::format(std::fixed, std::setprecision(0), high)) + ); + } + } } @@ -229,18 +480,55 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); dmethodconn.block(true); + Lmethodconn.block(true); + Cmethodconn.block(true); + C2methodconn.block(true); smethodconn.block(true); enaConn.block (true); + autochromaConn.block(true); medmethodconn.block(true); rgbmethodconn.block(true); methodmedconn.block(true); + + autochromaChanged (); dmethod->set_active (0); - if (pp->dirpyrDenoise.dmethod=="RGB") + if (pp->dirpyrDenoise.dmethod=="Lab") dmethod->set_active (0); - else if (pp->dirpyrDenoise.dmethod=="Lab") + else if (pp->dirpyrDenoise.dmethod=="RGB") dmethod->set_active (1); - + dmethodChanged (); + + Lmethod->set_active (0); + if (pp->dirpyrDenoise.Lmethod=="CUR") + Lmethod->set_active (0); + else if (pp->dirpyrDenoise.Lmethod=="SLI") + Lmethod->set_active (1); + LmethodChanged(); + + if(options.rtSettings.leveldnautsimpl==1){ + Cmethod->set_active (0); + if (pp->dirpyrDenoise.Cmethod=="MAN") + Cmethod->set_active (0); + else if (pp->dirpyrDenoise.Cmethod=="AUT") + Cmethod->set_active (1); + else if (pp->dirpyrDenoise.Cmethod=="PON") + Cmethod->set_active (2); + else if (pp->dirpyrDenoise.Cmethod=="PRE") + Cmethod->set_active (3); + CmethodChanged(); + } + else { + C2method->set_active (0); + if (pp->dirpyrDenoise.C2method=="MANU") + C2method->set_active (0); + else if (pp->dirpyrDenoise.C2method=="AUTO") + C2method->set_active (1); + else if (pp->dirpyrDenoise.C2method=="PREV") + C2method->set_active (2); + + C2methodChanged(); + } smethod->set_active (0); if (pp->dirpyrDenoise.smethod=="shal") @@ -259,10 +547,14 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { // methodmed->set_active (0); if (pp->dirpyrDenoise.methodmed=="Lonly") methodmed->set_active (0); - else if (pp->dirpyrDenoise.methodmed=="Lab") + else if (pp->dirpyrDenoise.methodmed=="ab") methodmed->set_active (1); + else if (pp->dirpyrDenoise.methodmed=="Lpab") + methodmed->set_active (2); + else if (pp->dirpyrDenoise.methodmed=="Lab") + methodmed->set_active (3); else if (pp->dirpyrDenoise.methodmed=="RGB") - methodmed->set_active (2); + methodmed->set_active (4); methodmedChanged(); medmethod->set_active (0); @@ -278,6 +570,8 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { medmethod->set_active (3); else if (pp->dirpyrDenoise.medmethod=="77") medmethod->set_active (4); + else if (pp->dirpyrDenoise.medmethod=="99") + medmethod->set_active (5); medmethodChanged(); rgbmethod->set_active (0); @@ -300,9 +594,15 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { if (!pedited->dirpyrDenoise.rgbmethod) rgbmethod->set_active (2); if (!pedited->dirpyrDenoise.medmethod) - medmethod->set_active (4); + medmethod->set_active (6); if (!pedited->dirpyrDenoise.methodmed) - methodmed->set_active (2); + methodmed->set_active (5); + if (!pedited->dirpyrDenoise.Cmethod) + Cmethod->set_active (4); + if (!pedited->dirpyrDenoise.C2method) + C2method->set_active (3); + if (!pedited->dirpyrDenoise.Lmethod) + Lmethod->set_active (2); luma->setEditedState (pedited->dirpyrDenoise.luma ? Edited : UnEdited); Ldetail->setEditedState (pedited->dirpyrDenoise.Ldetail ? Edited : UnEdited); @@ -315,6 +615,8 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { enabled->set_inconsistent (!pedited->dirpyrDenoise.enabled); enhance->set_inconsistent (!pedited->dirpyrDenoise.enhance); median->set_inconsistent (!pedited->dirpyrDenoise.median); + ccshape->setUnChanged (!pedited->dirpyrDenoise.cccurve); + // perform->set_inconsistent (!pedited->dirpyrDenoise.perform); } // perfconn.block (true); @@ -322,10 +624,12 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { enhance->set_active (pp->dirpyrDenoise.enhance); // perform->set_active (pp->dirpyrDenoise.perform); median->set_active (pp->dirpyrDenoise.median); + autochroma->set_active (pp->dirpyrDenoise.autochroma); // perfconn.block (false); lastEnabled = pp->dirpyrDenoise.enabled; lastmedian = pp->dirpyrDenoise.median; + lastautochroma = pp->dirpyrDenoise.autochroma; lastenhance = pp->dirpyrDenoise.enhance; // lastperform = pp->dirpyrDenoise.perform; luma->setValue (pp->dirpyrDenoise.luma); @@ -337,22 +641,32 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) { gamma->setValue (pp->dirpyrDenoise.gamma); passes->setValue (pp->dirpyrDenoise.passes); lshape->setCurve (pp->dirpyrDenoise.lcurve); + ccshape->setCurve (pp->dirpyrDenoise.cccurve); enaConn.block (false); + autochromaConn.block(false); + dmethodconn.block(false); + Lmethodconn.block(false); + Cmethodconn.block(false); + C2methodconn.block(false); smethodconn.block(false); medmethodconn.block(false); rgbmethodconn.block(false); methodmedconn.block(false); + updateNoiseLabel (); + enableListener (); } void DirPyrDenoise::setEditProvider (EditDataProvider *provider) { lshape->setEditProvider(provider); + ccshape->setEditProvider(provider); + } void DirPyrDenoise::autoOpenCurve () { - // Open up the first curve if selected - bool active = lshape->openIfNonlinear(); + lshape->openIfNonlinear(); + ccshape->openIfNonlinear(); } void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) { @@ -367,14 +681,19 @@ 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.autochroma = autochroma->get_active(); pp->dirpyrDenoise.lcurve = lshape->getCurve (); + pp->dirpyrDenoise.cccurve = ccshape->getCurve (); if (pedited) { pedited->dirpyrDenoise.dmethod = dmethod->get_active_row_number() != 2; + pedited->dirpyrDenoise.Lmethod = Lmethod->get_active_row_number() != 2; + pedited->dirpyrDenoise.Cmethod = Cmethod->get_active_row_number() != 4; + pedited->dirpyrDenoise.C2method = C2method->get_active_row_number() != 3; pedited->dirpyrDenoise.smethod = smethod->get_active_row_number() != 2; - pedited->dirpyrDenoise.medmethod = medmethod->get_active_row_number() != 4; + pedited->dirpyrDenoise.medmethod = medmethod->get_active_row_number() != 6; pedited->dirpyrDenoise.rgbmethod = rgbmethod->get_active_row_number() != 2; - pedited->dirpyrDenoise.methodmed = methodmed->get_active_row_number() != 2; + pedited->dirpyrDenoise.methodmed = methodmed->get_active_row_number() != 5; pedited->dirpyrDenoise.luma = luma->getEditedState (); pedited->dirpyrDenoise.Ldetail = Ldetail->getEditedState (); pedited->dirpyrDenoise.chroma = chroma->getEditedState (); @@ -385,16 +704,41 @@ 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.autochroma = !autochroma->get_inconsistent(); pedited->dirpyrDenoise.lcurve = !lshape->isUnChanged (); + pedited->dirpyrDenoise.cccurve = !ccshape->isUnChanged (); // pedited->dirpyrDenoise.perform = !perform->get_inconsistent(); } if (dmethod->get_active_row_number()==0) - pp->dirpyrDenoise.dmethod = "RGB"; - else if (dmethod->get_active_row_number()==1) pp->dirpyrDenoise.dmethod = "Lab"; + else if (dmethod->get_active_row_number()==1) + pp->dirpyrDenoise.dmethod = "RGB"; - if (smethod->get_active_row_number()==0) + if (Lmethod->get_active_row_number()==0) + pp->dirpyrDenoise.Lmethod = "CUR"; + else if (Lmethod->get_active_row_number()==1) + pp->dirpyrDenoise.Lmethod = "SLI"; + if(options.rtSettings.leveldnautsimpl==1){ + if (Cmethod->get_active_row_number()==0) + pp->dirpyrDenoise.Cmethod = "MAN"; + else if (Cmethod->get_active_row_number()==1) + pp->dirpyrDenoise.Cmethod = "AUT"; + else if (Cmethod->get_active_row_number()==2) + pp->dirpyrDenoise.Cmethod = "PON"; + else if (Cmethod->get_active_row_number()==3) + pp->dirpyrDenoise.Cmethod = "PRE"; + } + else + { + if (C2method->get_active_row_number()==0) + pp->dirpyrDenoise.C2method = "MANU"; + else if (C2method->get_active_row_number()==1) + pp->dirpyrDenoise.C2method = "AUTO"; + else if (C2method->get_active_row_number()==2) + pp->dirpyrDenoise.C2method = "PREV"; + } + if (smethod->get_active_row_number()==0) pp->dirpyrDenoise.smethod = "shal"; // else if (smethod->get_active_row_number()==1) // pp->dirpyrDenoise.smethod = "shbi"; @@ -410,8 +754,12 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) { if (methodmed->get_active_row_number()==0) pp->dirpyrDenoise.methodmed = "Lonly"; else if (methodmed->get_active_row_number()==1) - pp->dirpyrDenoise.methodmed = "Lab"; + pp->dirpyrDenoise.methodmed = "ab"; else if (methodmed->get_active_row_number()==2) + pp->dirpyrDenoise.methodmed = "Lpab"; + else if (methodmed->get_active_row_number()==3) + pp->dirpyrDenoise.methodmed = "Lab"; + else if (methodmed->get_active_row_number()==4) pp->dirpyrDenoise.methodmed = "RGB"; @@ -428,6 +776,8 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) { pp->dirpyrDenoise.medmethod = "55"; else if (medmethod->get_active_row_number()==4) pp->dirpyrDenoise.medmethod = "77"; + else if (medmethod->get_active_row_number()==5) + pp->dirpyrDenoise.medmethod = "99"; if (rgbmethod->get_active_row_number()==0) pp->dirpyrDenoise.rgbmethod = "soft"; @@ -438,10 +788,13 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) { } -void DirPyrDenoise::curveChanged () { +void DirPyrDenoise::curveChanged (CurveEditor* ce) { if (listener && enabled->get_active()) { + if (ce == lshape) listener->panelChanged (EvDPDNLCurve, M("HISTORY_CUSTOMCURVE")); + if (ce == ccshape) + listener->panelChanged (EvDPDNCCCurve, M("HISTORY_CUSTOMCURVE")); } } @@ -451,6 +804,125 @@ void DirPyrDenoise::dmethodChanged () { listener->panelChanged (EvDPDNmet, dmethod->get_active_text ()); } } +void DirPyrDenoise::LmethodChanged () { + if (!batchMode) { + if(Lmethod->get_active_row_number()==0) { // CUR + luma->hide(); + NoiscurveEditorG->show(); + } + else if(Lmethod->get_active_row_number()==1) { // SLI + luma->show(); + NoiscurveEditorG->hide(); + } + } + if (listener && (multiImage||enabled->get_active()) ) { + listener->panelChanged (EvDPDNLmet, Lmethod->get_active_text ()); + } +} + +void DirPyrDenoise::CmethodChanged () { + if (!batchMode) { + if(Cmethod->get_active_row_number()==0 ) { //MAN + chroma->show(); + redchro->show(); + bluechro->show(); + chroma->set_sensitive(true); + redchro->set_sensitive(true); + bluechro->set_sensitive(true); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + } + else if(Cmethod->get_active_row_number()==1) { // AUT + chroma->show(); + redchro->show(); + bluechro->show(); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } + else if(Cmethod->get_active_row_number()==2) { // PON + chroma->hide(); + redchro->hide(); + bluechro->hide(); + NoiseLabels->hide(); + TileLabels->hide(); + PrevLabels->hide(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } + else if(Cmethod->get_active_row_number()==3) { // PRE + chroma->show(); + redchro->show(); + bluechro->show(); + NoiseLabels->show(); + TileLabels->show(); + PrevLabels->show(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } + + } + if (listener && (multiImage||enabled->get_active()) ) { + listener->panelChanged (EvDPDNCmet, Cmethod->get_active_text ()); + } +} + +void DirPyrDenoise::C2methodChanged () { + if (!batchMode) { + if(C2method->get_active_row_number()==0 ) { //MAN + chroma->show(); + redchro->show(); + bluechro->show(); + chroma->set_sensitive(true); + redchro->set_sensitive(true); + bluechro->set_sensitive(true); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + } + else if(C2method->get_active_row_number()==1) { // AUTO + chroma->show(); + redchro->show(); + bluechro->show(); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } + else if(C2method->get_active_row_number()==2) { // PREV + chroma->show(); + redchro->show(); + bluechro->show(); + NoiseLabels->show(); + TileLabels->hide(); + PrevLabels->hide(); + + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } + + + } + if (listener && (multiImage||enabled->get_active()) ) { + listener->panelChanged (EvDPDNC2met, C2method->get_active_text ()); + } +} + void DirPyrDenoise::smethodChanged () { @@ -469,7 +941,7 @@ void DirPyrDenoise::medmethodChanged () { void DirPyrDenoise::rgbmethodChanged () { ctboxrgb->hide(); - if(methodmed->get_active_row_number()==2) ctboxrgb->show(); + if(methodmed->get_active_row_number()==4) ctboxrgb->show(); if (listener && (multiImage||enabled->get_active()) && median->get_active()) { listener->panelChanged (EvDPDNrgbmet, rgbmethod->get_active_text ()); } @@ -478,7 +950,7 @@ void DirPyrDenoise::rgbmethodChanged () { void DirPyrDenoise::methodmedChanged () { - if(methodmed->get_active_row_number()==2) {ctboxrgb->show();ctbox->hide();} + if(methodmed->get_active_row_number()==4) {ctboxrgb->show();ctbox->hide();} else {ctboxrgb->hide();ctbox->show();} if (listener && (multiImage||enabled->get_active()) && median->get_active()) { @@ -555,8 +1027,10 @@ void DirPyrDenoise::enabledChanged () { } if (listener) { - if (enabled->get_active ()) + if (enabled->get_active ()) {autochromaChanged (); + listener->panelChanged (EvDPDNEnabled, M("GENERAL_ENABLED")); + } else listener->panelChanged (EvDPDNEnabled, M("GENERAL_DISABLED")); } @@ -578,6 +1052,7 @@ void DirPyrDenoise::enhanceChanged () { } if (listener) { + if (enhance->get_active ()) listener->panelChanged (EvDPDNenhance, M("GENERAL_ENABLED")); else @@ -603,16 +1078,59 @@ void DirPyrDenoise::medianChanged () { if (listener) { if (median->get_active ()) { listener->panelChanged (EvDPDNmedian, M("GENERAL_ENABLED")); - // medmethodChanged ();rgbmethodChanged ();methodmedChanged (); } else { listener->panelChanged (EvDPDNmedian, M("GENERAL_DISABLED")); - // medmethodChanged ();rgbmethodChanged ();methodmedChanged (); } } } +void DirPyrDenoise::autochromaChanged () { +// printf("Autochroma\n"); + if (batchMode) { + if (autochroma->get_inconsistent()) { + autochroma->set_inconsistent (false); + autochromaConn.block (true); + autochroma->set_active (false); + autochromaConn.block (false); + } + else if (lastautochroma) + autochroma->set_inconsistent (true); + + lastautochroma = autochroma->get_active (); + } + if (autochroma->get_active ()) + { + chroma->set_sensitive(false); + redchro->set_sensitive(false); + bluechro->set_sensitive(false); + } + else + { + chroma->set_sensitive(true); + redchro->set_sensitive(true); + bluechro->set_sensitive(true); + } + + if (listener) { + if (autochroma->get_active ()) + { listener->panelChanged (EvDPDNautochroma, M("GENERAL_ENABLED")); + // chroma->set_sensitive(false); + // redchro->set_sensitive(false); + // bluechro->set_sensitive(false); + } + else + {listener->panelChanged (EvDPDNautochroma, M("GENERAL_DISABLED")); + //chroma->set_sensitive(true); + //redchro->set_sensitive(true); + //bluechro->set_sensitive(true); + } + + + } +} + /* void DirPyrDenoise::perform_toggled () { @@ -650,8 +1168,12 @@ void DirPyrDenoise::setBatchMode (bool batchMode) { gamma->showEditedCB (); passes->showEditedCB (); NoiscurveEditorG->setBatchMode (batchMode); + CCcurveEditorG->setBatchMode (batchMode); dmethod->append_text (M("GENERAL_UNCHANGED")); + Lmethod->append_text (M("GENERAL_UNCHANGED")); + Cmethod->append_text (M("GENERAL_UNCHANGED")); + C2method->append_text (M("GENERAL_UNCHANGED")); smethod->append_text (M("GENERAL_UNCHANGED")); medmethod->append_text (M("GENERAL_UNCHANGED")); methodmed->append_text (M("GENERAL_UNCHANGED")); @@ -670,6 +1192,47 @@ void DirPyrDenoise::setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chro passes->setAddMode(passesadd); } +void DirPyrDenoise::colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller *caller) { + + float R, G, B; + + if (elemType==ColorCaller::CCET_VERTICAL_BAR) + valY = 0.5; + + if (callerId == 1) { // ch - main curve + + Color::hsv2rgb01(float(valX), float(valY), 0.5f, R, G, B); + } + else if (callerId == 2) { // cc - bottom bar + + float value = (1.f - 0.7f) * float(valX) + 0.7f; + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } + else if (callerId == 3) { // lc - bottom bar + + float value = (1.f - 0.7f) * float(valX) + 0.7f; + // whole hue range + // Y axis / from 0.15 up to 0.75 (arbitrary values; was 0.45 before) + Color::hsv2rgb01(float(valY), float(valX), value, R, G, B); + } + + else if (callerId == 4) { // LH - bottom bar + Color::hsv2rgb01(float(valX), 0.5f, float(valY), R, G, B); + } + else if (callerId == 5) { // HH - bottom bar + float h = float((valY - 0.5) * 0.3 + valX); + if (h > 1.0f) + h -= 1.0f; + else if (h < 0.0f) + h += 1.0f; + Color::hsv2rgb01(h, 0.5f, 0.5f, R, G, B); + } + caller->ccRed = double(R); + caller->ccGreen = double(G); + caller->ccBlue = double(B); +} void DirPyrDenoise::trimValues (rtengine::procparams::ProcParams* pp) { diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h index d40760b87..92843231a 100644 --- a/rtgui/dirpyrdenoise.h +++ b/rtgui/dirpyrdenoise.h @@ -26,11 +26,13 @@ #include "curveeditorgroup.h" #include "colorprovider.h" #include "guiutils.h" +#include "options.h" -class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider { +class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoChromaListener, public CurveListener, public ColorProvider { protected: CurveEditorGroup* NoiscurveEditorG; + CurveEditorGroup* CCcurveEditorG; Adjuster* luma; Adjuster* Ldetail; Adjuster* chroma; @@ -39,21 +41,33 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol Adjuster* gamma; Adjuster* passes; FlatCurveEditor* lshape; + FlatCurveEditor* ccshape; Gtk::CheckButton* enabled; bool lastEnabled; sigc::connection enaConn; Gtk::CheckButton* enhance; bool lastenhance; - sigc::connection enhanConn, medianConn; + sigc::connection enhanConn, medianConn, autochromaConn; Gtk::CheckButton* median; bool lastmedian; + Gtk::CheckButton* autochroma; + bool lastautochroma; + Gtk::Label* NoiseLabels; + Gtk::Label* TileLabels; + Gtk::Label* PrevLabels; // Gtk::CheckButton* perform; // bool lastperform; // sigc::connection perfconn; MyComboBoxText* dmethod; sigc::connection dmethodconn; + MyComboBoxText* Lmethod; + sigc::connection Lmethodconn; + MyComboBoxText* Cmethod; + sigc::connection Cmethodconn; + MyComboBoxText* C2method; + sigc::connection C2methodconn; MyComboBoxText* smethod; sigc::connection smethodconn; MyComboBoxText* medmethod; @@ -65,8 +79,21 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol MyComboBoxText* rgbmethod; sigc::connection rgbmethodconn; Gtk::HBox* ctboxrgb; + double nextchroma; + double nextred; + double nextblue; + double nextnresid; + double nexthighresid; + Gtk::HBox* ctboxL; + Gtk::HBox* ctboxC; + Gtk::HBox* ctboxC2; + int nexttileX; + int nexttileY; + int nextprevX; + int nextprevY; + int nextsizeT; + int nextsizeP; - public: DirPyrDenoise (); @@ -76,7 +103,7 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol 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 curveChanged (CurveEditor* ce); void setEditProvider (EditDataProvider *provider); void autoOpenCurve (); @@ -84,15 +111,33 @@ class DirPyrDenoise : public ToolParamBlock, public AdjusterListener, public Fol void enabledChanged (); void enhanceChanged (); void medianChanged (); + void autochromaChanged (); + void chromaChanged (double autchroma, double autred, double autblue); + bool chromaComputed_ (); + void noiseChanged (double nresid, double highresid); + bool noiseComputed_ (); + void noiseTilePrev (int tileX, int tileY, int prevX, int prevY, int sizeT, int sizeP); + bool TilePrevComputed_ (); + // void perform_toggled (); + void updateNoiseLabel (); + void LmethodChanged (); + void CmethodChanged (); + void C2methodChanged (); + void updateTileLabel (); + void updatePrevLabel (); + void dmethodChanged (); void medmethodChanged (); void methodmedChanged (); void rgbmethodChanged (); void smethodChanged (); + virtual void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); void setAdjusterBehavior (bool lumaadd, bool lumdetadd, bool chromaadd, bool chromaredadd, bool chromablueadd, bool gammaadd, bool passesadd); void trimValues (rtengine::procparams::ProcParams* pp); + Glib::ustring getSettingString (); + }; #endif diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 6be0f7bf8..a9cf1d950 100755 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -33,12 +33,12 @@ using namespace rtengine::procparams; EditorPanel::EditorPanel (FilePanel* filePanel) : beforePreviewHandler(NULL), beforeIarea(NULL), beforeBox(NULL), afterBox(NULL), afterHeaderBox(NULL), parent(NULL), ipc(NULL), beforeIpc(NULL), isProcessing(false), catalogPane(NULL), iHistoryShow(NULL), iHistoryHide(NULL), iBeforeLockON(NULL),iBeforeLockOFF(NULL), iRightPanel_1_Show(NULL), iRightPanel_1_Hide(NULL), iTopPanel_1_Show(NULL), iTopPanel_1_Hide(NULL), openThm(NULL) { - + epih = new EditorPanelIdleHelper; epih->epanel = this; epih->destroyed = false; epih->pending = 0; - + //rtengine::befaf=true; processingStartedTime = 0; firstProcessingDone = false; @@ -349,9 +349,9 @@ EditorPanel::~EditorPanel () { delete beforeIarea; beforeIarea = NULL; - if (beforeIpc) + if (beforeIpc){ beforeIpc->setPreviewImageListener (NULL); - + } delete beforePreviewHandler; beforePreviewHandler = NULL; if (beforeIpc) @@ -375,19 +375,19 @@ EditorPanel::~EditorPanel () { delete catalogPane; if (iTopPanel_1_Show) delete iTopPanel_1_Show; - if (iTopPanel_1_Hide) delete iTopPanel_1_Hide; - if (iHistoryShow) - delete iHistoryShow; - if (iHistoryHide) - delete iHistoryHide; - if(iBeforeLockON) - delete iBeforeLockON; - if(iBeforeLockOFF) - delete iBeforeLockOFF; - if(iRightPanel_1_Show) - delete iRightPanel_1_Show; - if(iRightPanel_1_Hide) - delete iRightPanel_1_Hide; + if (iTopPanel_1_Hide) delete iTopPanel_1_Hide; + if (iHistoryShow) + delete iHistoryShow; + if (iHistoryHide) + delete iHistoryHide; + if(iBeforeLockON) + delete iBeforeLockON; + if(iBeforeLockOFF) + delete iBeforeLockOFF; + if(iRightPanel_1_Show) + delete iRightPanel_1_Show; + if(iRightPanel_1_Hide) + delete iRightPanel_1_Hide; } void EditorPanel::leftPaneButtonReleased(GdkEventButton *event) { @@ -453,6 +453,7 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) { lastSaveAsFileName = removeExtension (Glib::path_get_basename (fname)); previewHandler = new PreviewHandler (); + previewHandler2 = new PreviewHandler (); this->isrc = isrc; ipc = rtengine::StagedImageProcessor::create (isrc); @@ -514,12 +515,14 @@ void EditorPanel::close () { rtengine::ImageSource* is=isrc->getImageSource(); is->setProgressListener( NULL ); - if (ipc) + if (ipc) { ipc->setPreviewImageListener (NULL); + } - if (beforeIpc) + if (beforeIpc){ beforeIpc->setPreviewImageListener (NULL); - + } + delete previewHandler; previewHandler= NULL; @@ -862,12 +865,12 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) { bool ctrl = event->state & GDK_CONTROL_MASK; bool shift = event->state & GDK_SHIFT_MASK; - bool alt = event->state & GDK_MOD1_MASK; -#ifdef __WIN32__ - bool altgr = event->state & GDK_MOD2_MASK; -#else - bool altgr = event->state & GDK_MOD5_MASK; -#endif + bool alt = event->state & GDK_MOD1_MASK; +#ifdef __WIN32__ + bool altgr = event->state & GDK_MOD2_MASK; +#else + bool altgr = event->state & GDK_MOD5_MASK; +#endif // Editor Layout switch(event->keyval) { @@ -906,16 +909,16 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) { } break; } -#ifdef __WIN32__ - if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x39 ) { +#ifdef __WIN32__ + if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x39 ) { iareapanel->imageArea->previewModePanel->togglebackColor(); return true; - } -#else - if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x12 ) { - iareapanel->imageArea->previewModePanel->togglebackColor(); - return true; - } + } +#else + if (!alt && !ctrl && !altgr && event->hardware_keycode == 0x12 ) { + iareapanel->imageArea->previewModePanel->togglebackColor(); + return true; + } #endif if (!alt){ if (!ctrl) { @@ -945,13 +948,13 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) { case GDK_z://GDK_1 iareapanel->imageArea->zoomPanel->zoom11Clicked(); return true; -/* -#ifndef __WIN32__ - case GDK_9: // toggle background color of the preview +/* +#ifndef __WIN32__ + case GDK_9: // toggle background color of the preview iareapanel->imageArea->previewModePanel->togglebackColor(); - return true; + return true; #endif -*/ +*/ case GDK_r: //preview mode Red iareapanel->imageArea->previewModePanel->toggleR(); return true; @@ -1437,7 +1440,6 @@ void EditorPanel::beforeAfterToggled () { removeIfThere (beforeAfterBox, beforeBox, false); removeIfThere (afterBox, afterHeaderBox, false); - if (beforeIarea) { if (beforeIpc) beforeIpc->stopProcessing (); @@ -1446,7 +1448,8 @@ void EditorPanel::beforeAfterToggled () { delete beforeIarea; beforeIarea = NULL; if (beforeIpc) - beforeIpc->setPreviewImageListener (NULL); + { beforeIpc->setPreviewImageListener (NULL); + } delete beforePreviewHandler; beforePreviewHandler = NULL; if (beforeIpc) @@ -1455,6 +1458,7 @@ void EditorPanel::beforeAfterToggled () { } if (beforeAfter->get_active ()) { + int errorCode=0; rtengine::InitialImage *beforeImg = rtengine::InitialImage::load ( isrc->getImageSource ()->getFileName(), openThm->getType()==FT_Raw , &errorCode, NULL); if( !beforeImg || errorCode ) diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 26ad1db6a..d038c0dd2 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -85,6 +85,7 @@ class EditorPanel : public Gtk::VBox, ImageAreaPanel* iareapanel; PreviewHandler* previewHandler; PreviewHandler* beforePreviewHandler; // for the before-after view + PreviewHandler* previewHandler2; Navigator* navigator; ImageAreaPanel* beforeIarea; // for the before-after view Gtk::VBox* beforeBox; diff --git a/rtgui/options.cc b/rtgui/options.cc index ff8ea8847..5cdfaddb9 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -519,6 +519,11 @@ void Options::setDefaults () { rtSettings.viewingdevice=0; rtSettings.viewingdevicegrey=3; rtSettings.viewinggreySc=1; + rtSettings.leveldnv=2; + rtSettings.leveldnti=0; + rtSettings.leveldnaut=0; + rtSettings.leveldnliss=0; + rtSettings.leveldnautsimpl=0; rtSettings.monitorProfile = ""; rtSettings.autoMonitorProfile = false; @@ -546,6 +551,12 @@ void Options::setDefaults () { rtSettings.autocielab=true; rtSettings.denoiselabgamma=2; rtSettings.HistogramWorking = false; + + rtSettings.nrauto = 10;//between 2 and 20 + rtSettings.nrautomax = 40;//between 5 and 100 + rtSettings.nrhigh = 0.45;//between 0.1 and 0.9 + rtSettings.nrwavlevel = 1;//integer between 0 and 2 + // rtSettings.colortoningab =0.7; //rtSettings.decaction =0.3; // rtSettings.ciebadpixgauss=false; @@ -716,6 +727,17 @@ if (keyFile.has_group ("Clipping Indication")) { if (keyFile.has_group ("Performance")) { if (keyFile.has_key ("Performance", "RgbDenoiseThreadLimit")) rgbDenoiseThreadLimit = keyFile.get_integer ("Performance", "RgbDenoiseThreadLimit"); + if( keyFile.has_key ("Performance", "NRauto")) rtSettings.nrauto = keyFile.get_double("Performance", "NRauto"); + if( keyFile.has_key ("Performance", "NRautomax")) rtSettings.nrautomax = keyFile.get_double("Performance", "NRautomax"); + if( keyFile.has_key ("Performance", "NRhigh")) rtSettings.nrhigh = keyFile.get_double("Performance", "NRhigh"); + if( keyFile.has_key ("Performance", "NRWavlevel")) rtSettings.nrwavlevel = keyFile.get_integer("Performance", "NRWavlevel"); + if (keyFile.has_key ("Performance", "LevNR")) rtSettings.leveldnv = keyFile.get_integer("Performance", "LevNR"); + if (keyFile.has_key ("Performance", "LevNRTI")) rtSettings.leveldnti = keyFile.get_integer("Performance", "LevNRTI"); + if (keyFile.has_key ("Performance", "LevNRAUT")) rtSettings.leveldnaut = keyFile.get_integer("Performance", "LevNRAUT"); + if (keyFile.has_key ("Performance", "LevNRLISS")) rtSettings.leveldnliss = keyFile.get_integer("Performance", "LevNRLISS"); + if (keyFile.has_key ("Performance", "SIMPLNRAUT")) rtSettings.leveldnautsimpl = keyFile.get_integer("Performance", "SIMPLNRAUT"); + + } if (keyFile.has_group ("GUI")) { @@ -988,6 +1010,15 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_boolean ("Clipping Indication", "BlinkClipped", blinkClipped); keyFile.set_integer ("Performance", "RgbDenoiseThreadLimit", rgbDenoiseThreadLimit); + keyFile.set_double ("Performance", "NRauto", rtSettings.nrauto); + keyFile.set_double ("Performance", "NRautomax", rtSettings.nrautomax); + keyFile.set_double ("Performance", "NRhigh", rtSettings.nrhigh); + keyFile.set_integer ("Performance", "NRWavlevel", rtSettings.nrwavlevel); + keyFile.set_integer ("Performance", "LevNR", rtSettings.leveldnv); + keyFile.set_integer ("Performance", "LevNRTI", rtSettings.leveldnti); + keyFile.set_integer ("Performance", "LevNRAUT", rtSettings.leveldnaut); + keyFile.set_integer ("Performance", "LevNRLISS", rtSettings.leveldnliss); + keyFile.set_integer ("Performance", "SIMPLNRAUT", rtSettings.leveldnautsimpl); keyFile.set_string ("Output", "Format", saveFormat.format); keyFile.set_integer ("Output", "JpegQuality", saveFormat.jpegQuality); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 0126f4aef..585f690e8 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -182,7 +182,9 @@ void ParamsEdited::set (bool v) { dirpyrDenoise.enhance = v; // dirpyrDenoise.perform = v; dirpyrDenoise.lcurve = v; + dirpyrDenoise.cccurve = v; dirpyrDenoise.median = v; + dirpyrDenoise.autochroma = v; dirpyrDenoise.luma = v; dirpyrDenoise.Ldetail = v; dirpyrDenoise.chroma = v; @@ -191,6 +193,9 @@ void ParamsEdited::set (bool v) { dirpyrDenoise.gamma = v; dirpyrDenoise.passes = v; dirpyrDenoise.dmethod = v; + dirpyrDenoise.Lmethod = v; + dirpyrDenoise.Cmethod = v; + dirpyrDenoise.C2method = v; dirpyrDenoise.smethod = v; dirpyrDenoise.medmethod = v; dirpyrDenoise.methodmed = v; @@ -317,7 +322,7 @@ void ParamsEdited::set (bool v) { raw.caCorrection = v; raw.caBlue = v; raw.caRed = v; - raw.hotPixelFilter = v; + raw.hotPixelFilter = v; raw.deadPixelFilter = v; raw.hotDeadPixelThresh = v; raw.darkFrame = v; @@ -513,9 +518,11 @@ void ParamsEdited::initFrom (const std::vector dirpyrDenoise.enabled = dirpyrDenoise.enabled && p.dirpyrDenoise.enabled == other.dirpyrDenoise.enabled; dirpyrDenoise.enhance = dirpyrDenoise.enhance && p.dirpyrDenoise.enhance == other.dirpyrDenoise.enhance; dirpyrDenoise.median = dirpyrDenoise.median && p.dirpyrDenoise.median == other.dirpyrDenoise.median; + dirpyrDenoise.autochroma = dirpyrDenoise.autochroma && p.dirpyrDenoise.autochroma == other.dirpyrDenoise.autochroma; // 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.cccurve = dirpyrDenoise.cccurve && p.dirpyrDenoise.cccurve == other.dirpyrDenoise.cccurve; 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; @@ -523,6 +530,9 @@ 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.Lmethod = dirpyrDenoise.Lmethod && p.dirpyrDenoise.Lmethod == other.dirpyrDenoise.Lmethod; + dirpyrDenoise.Cmethod = dirpyrDenoise.Cmethod && p.dirpyrDenoise.Cmethod == other.dirpyrDenoise.Cmethod; + dirpyrDenoise.C2method = dirpyrDenoise.C2method && p.dirpyrDenoise.C2method == other.dirpyrDenoise.C2method; 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; @@ -849,8 +859,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (dirpyrDenoise.enabled) toEdit.dirpyrDenoise.enabled = mods.dirpyrDenoise.enabled; if (dirpyrDenoise.enhance) toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance; if (dirpyrDenoise.median) toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median; + if (dirpyrDenoise.autochroma) toEdit.dirpyrDenoise.autochroma = mods.dirpyrDenoise.autochroma; 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.cccurve) toEdit.dirpyrDenoise.cccurve = mods.dirpyrDenoise.cccurve; 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; @@ -859,6 +871,9 @@ 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.Lmethod) toEdit.dirpyrDenoise.Lmethod = mods.dirpyrDenoise.Lmethod; + if (dirpyrDenoise.Cmethod) toEdit.dirpyrDenoise.Cmethod = mods.dirpyrDenoise.Cmethod; + if (dirpyrDenoise.C2method) toEdit.dirpyrDenoise.C2method = mods.dirpyrDenoise.C2method; 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; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 2d43cfe3d..aeac5bb74 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -264,6 +264,7 @@ public: bool enabled; bool enhance; bool median; + bool autochroma; bool Ldetail; bool luma; bool chroma; @@ -271,9 +272,13 @@ public: bool bluechro; bool gamma; bool lcurve; + bool cccurve; // bool perform; bool dmethod; + bool Lmethod; + bool Cmethod; + bool C2method; bool smethod; bool medmethod; bool methodmed; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 4d3c27c71..5d14b45dc 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -490,7 +490,13 @@ Gtk::Widget* Preferences::getProcParamsPanel () { } Gtk::Widget* Preferences::getPerformancePanel () { + Gtk::VBox* mvbsd = Gtk::manage( new Gtk::VBox () ); + + Gtk::Frame* fdenoise = Gtk::manage( new Gtk::Frame (M("PREFERENCES_NOISE")) ); + Gtk::VBox* mainContainer = Gtk::manage( new Gtk::VBox () ); + mainContainer->set_border_width (4); + mainContainer->set_spacing(4); Gtk::HBox* threadLimitHB = Gtk::manage( new Gtk::HBox () ); @@ -509,10 +515,89 @@ Gtk::Widget* Preferences::getPerformancePanel () { rgbDenoiseTreadLimitSB->set_range (0, maxThreadNumber); threadLimitHB->pack_start (*RGBDTLl, Gtk::PACK_SHRINK, 0); threadLimitHB->pack_end (*rgbDenoiseTreadLimitSB, Gtk::PACK_SHRINK, 0); + Gtk::Label* restartNeeded3 = Gtk::manage( new Gtk::Label (Glib::ustring(" (") + M("PREFERENCES_APPLNEXTSTARTUP") + ")") ); + Gtk::Label* restartNeeded4 = Gtk::manage( new Gtk::Label (Glib::ustring(" (") + M("PREFERENCES_APPLNEXTSTARTUP") + ")") ); + Gtk::Label* restartNeeded5 = Gtk::manage( new Gtk::Label (Glib::ustring(" (") + M("PREFERENCES_APPLNEXTSTARTUP") + ")") ); + Gtk::Label* restartNeeded6 = Gtk::manage( new Gtk::Label (Glib::ustring(" (") + M("PREFERENCES_APPLNEXTSTARTUP") + ")") ); + Gtk::Label* restartNeeded7 = Gtk::manage( new Gtk::Label (Glib::ustring(" (") + M("PREFERENCES_APPLNEXTSTARTUP") + ")") ); + Gtk::Label* restartNeeded8 = Gtk::manage( new Gtk::Label (Glib::ustring(" (") + M("PREFERENCES_APPLNEXTSTARTUP") + ")") ); + Gtk::Label* dnlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LEVDN")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnautlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LEVAUTDN")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnautsimpllab = Gtk::manage (new Gtk::Label (M("PREFERENCES_SIMPLAUT")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* dntilab = Gtk::manage (new Gtk::Label (M("PREFERENCES_TINB")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnwavlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_WAVLEV")+":", Gtk::ALIGN_LEFT)); + Gtk::Label* dnlisslab = Gtk::manage (new Gtk::Label (M("PREFERENCES_LISS")+":", Gtk::ALIGN_LEFT)); + + dnv = Gtk::manage (new Gtk::ComboBoxText ()); + dnv->append_text (M("PREFERENCES_MIN")); + dnv->append_text (M("PREFERENCES_SMA")); + dnv->append_text (M("PREFERENCES_MED")); + dnv->append_text (M("PREFERENCES_MAX")); + dnaut = Gtk::manage (new Gtk::ComboBoxText ()); + dnaut->append_text (M("PREFERENCES_AUTLOW")); + dnaut->append_text (M("PREFERENCES_AUTSTD")); + + dnautsimpl = Gtk::manage (new Gtk::ComboBoxText ()); + dnautsimpl->append_text (M("PREFERENCES_STDAUT")); + dnautsimpl->append_text (M("PREFERENCES_EXPAUT")); + + dnliss = Gtk::manage (new Gtk::ComboBoxText ()); + dnliss->append_text (M("PREFERENCES_AUTLISVLOW"));//very low + dnliss->append_text (M("PREFERENCES_AUTLISLOW"));//low + dnliss->append_text (M("PREFERENCES_AUTLISSTD"));//med + dnliss->append_text (M("PREFERENCES_AUTLISMAX"));//max + + dnti = Gtk::manage (new Gtk::ComboBoxText ()); + dnti->append_text (M("PREFERENCES_TISTD")); + dnti->append_text (M("PREFERENCES_TIMAX")); + + dnwavlev = Gtk::manage (new Gtk::ComboBoxText ()); + dnwavlev->append_text (M("PREFERENCES_WLZER")); + dnwavlev->append_text (M("PREFERENCES_WLONE")); + dnwavlev->append_text (M("PREFERENCES_WLTWO")); + + Gtk::Table* colon = Gtk::manage (new Gtk::Table (6, 3)); + colon->attach (*dnlab, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnv, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); + colon->attach (*restartNeeded3, 2, 3, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnautlab, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnaut, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); + colon->attach (*restartNeeded4, 2, 3, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnautsimpllab, 0, 1, 2, 3, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnautsimpl, 1, 2, 2, 3, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); + colon->attach (*restartNeeded8, 2, 3, 2, 3, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnlisslab, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnliss, 1, 2, 3, 4, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); + colon->attach (*restartNeeded5, 2, 3, 3, 4, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dntilab, 0, 1, 4, 5, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnti, 1, 2, 4, 5, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); + colon->attach (*restartNeeded6, 2, 3, 4, 5, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnwavlab, 0, 1, 5, 6, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon->attach (*dnwavlev, 1, 2, 5, 6, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); + colon->attach (*restartNeeded7, 2, 3, 5, 6, Gtk::FILL, Gtk::SHRINK, 2, 2); + + mainContainer->pack_start (*colon, Gtk::PACK_SHRINK, 4); + + /* Gtk::Label* dntilab = Gtk::manage (new Gtk::Label (M("PREFERENCES_TINB")+":", Gtk::ALIGN_LEFT)); + + dnti = Gtk::manage (new Gtk::ComboBoxText ()); + dnti->append_text (M("PREFERENCES_TISTD")); + dnti->append_text (M("PREFERENCES_TIMAX")); + Gtk::Table* colon2 = Gtk::manage (new Gtk::Table (1, 3)); + colon2->attach (*dntilab, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2); + colon2->attach (*dnti, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); + colon2->attach (*restartNeeded4, 2, 3, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2); + mainContainer->pack_start (*colon2, Gtk::PACK_SHRINK, 4); +*/ + mainContainer->pack_start(*threadLimitHB, Gtk::PACK_SHRINK, 4); + fdenoise->add (*mainContainer); + mvbsd->pack_start (*fdenoise, Gtk::PACK_SHRINK, 4); - return mainContainer; + // return mainContainer; + return mvbsd; + } Gtk::Widget* Preferences::getColorManagementPanel () { @@ -1229,6 +1314,12 @@ void Preferences::storePreferences () { // moptions.rtSettings.autocielab = cbAutocielab->get_active (); moptions.rtSettings.ciecamfloat = cbciecamfloat->get_active (); moptions.rtSettings.HistogramWorking = ckbHistogramWorking->get_active (); + moptions.rtSettings.leveldnv = dnv->get_active_row_number (); + moptions.rtSettings.leveldnti = dnti->get_active_row_number (); + moptions.rtSettings.leveldnliss = dnliss->get_active_row_number (); + moptions.rtSettings.leveldnaut = dnaut->get_active_row_number (); + moptions.rtSettings.nrwavlevel = dnwavlev->get_active_row_number (); + moptions.rtSettings.leveldnautsimpl = dnautsimpl->get_active_row_number (); if (sdcurrent->get_active ()) moptions.startupDir = STARTUPDIR_CURRENT; @@ -1328,6 +1419,13 @@ void Preferences::fillPreferences () { view->set_active (moptions.rtSettings.viewingdevice); grey->set_active (moptions.rtSettings.viewingdevicegrey); greySc->set_active (moptions.rtSettings.viewinggreySc); + dnv->set_active (moptions.rtSettings.leveldnv); + dnti->set_active (moptions.rtSettings.leveldnti); + dnliss->set_active (moptions.rtSettings.leveldnliss); + dnaut->set_active (moptions.rtSettings.leveldnaut); + dnautsimpl->set_active (moptions.rtSettings.leveldnautsimpl); + dnwavlev->set_active (moptions.rtSettings.nrwavlevel); + // cbAutocielab->set_active (moptions.rtSettings.autocielab); cbciecamfloat->set_active (moptions.rtSettings.ciecamfloat); ckbHistogramWorking->set_active (moptions.rtSettings.HistogramWorking); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index cda32a649..21bb42584 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -95,6 +95,12 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener { Gtk::ComboBoxText* view; Gtk::ComboBoxText* grey; Gtk::ComboBoxText* greySc; + Gtk::ComboBoxText* dnv; + Gtk::ComboBoxText* dnti; + Gtk::ComboBoxText* dnaut; + Gtk::ComboBoxText* dnautsimpl; + Gtk::ComboBoxText* dnwavlev; + Gtk::ComboBoxText* dnliss; Gtk::ComboBoxText* theme; Gtk::CheckButton* slimUI; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index fe1b39240..eba820e93 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -391,6 +391,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool ipc->setAutoCamListener (colorappearance); ipc->setAutoBWListener (blackwhite); ipc->setAutoColorTonListener (colortoning); + ipc->setAutoChromaListener (dirpyrdenoise); ipc->setSizeListener (crop); ipc->setSizeListener (resize);