From fae7971dcc56d95fd2701ac5643d957051090958 Mon Sep 17 00:00:00 2001 From: jdc Date: Wed, 3 Apr 2013 07:28:20 +0200 Subject: [PATCH] LMMSE improves speed and sets a slider to improve processing see issue1802 --- rtdata/languages/default | 4 + rtengine/color.cc | 24 ++- rtengine/color.h | 11 +- rtengine/demosaic_algos.cc | 366 +++++++++++++++++++++++++++---------- rtengine/procevents.h | 5 +- rtengine/procparams.cc | 5 + rtengine/procparams.h | 2 + rtengine/rawimagesource.cc | 20 +- rtengine/rawimagesource.h | 5 +- rtengine/refreshmap.cc | 3 +- rtengine/sleef.c | 17 +- rtgui/exportpanel.cc | 8 + rtgui/exportpanel.h | 2 + rtgui/filecatalog.cc | 1 + rtgui/options.cc | 5 +- rtgui/options.h | 1 + rtgui/paramsedited.cc | 6 +- rtgui/paramsedited.h | 1 + rtgui/partialpastedlg.cc | 9 +- rtgui/partialpastedlg.h | 3 +- rtgui/rawprocess.cc | 42 ++++- rtgui/rawprocess.h | 2 + 22 files changed, 413 insertions(+), 129 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 343def8f7..97b50d105 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -430,6 +430,7 @@ HISTORY_MSG_200;CAMO2 - Tone mapping using CIECAM02 Q HISTORY_MSG_201;NR - Delta Chrominance red HISTORY_MSG_202;NR - Delta Chrominance blue HISTORY_MSG_203;NR - Method +HISTORY_MSG_204;LMMSE enhancement steps HISTORY_NEWSNAPSHOTAS;As... HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s @@ -654,6 +655,7 @@ PARTIALPASTE_RAWGROUP;Raw Settings PARTIALPASTE_RAW_ALLENHANCE;Apply post demosaic artifact/noise reduction PARTIALPASTE_RAW_DCBENHANCE;Apply DCB enhancement step PARTIALPASTE_RAW_DCBITERATIONS;Number of DCB iterations +PARTIALPASTE_RAW_LMMSEITERATIONS;LMMSE enhancement steps PARTIALPASTE_RAW_DMETHOD;Demosaic method PARTIALPASTE_RAW_FALSECOLOR;Demosaic false color suppression steps PARTIALPASTE_RESIZE;Resize @@ -1180,6 +1182,8 @@ TP_RAWEXPOS_TWOGREEN;Two greens together TP_RAW_ALLENHANCE;Post-Demosaic Artifact/Noise Reduction TP_RAW_DCBENHANCE;DCB Enhancement Step TP_RAW_DCBITERATIONS;Number of DCB Iterations +TP_RAW_LMMSEITERATIONS;LMMSE enhancement Steps +TP_RAW_LMMSE_TOOLTIP;Add gamma (step 1) - Adds median (step 2,3,4), then Add a refinement (step 5,6) to reduce artifacts and improve the signal to noise ratio TP_RAW_DMETHOD;Method TP_RAW_DMETHOD_PROGRESSBAR;%1 demosaicing... TP_RAW_DMETHOD_PROGRESSBAR_REFINE;Demosaicing refinement... diff --git a/rtengine/color.cc b/rtengine/color.cc index 4e31a6aeb..da81a8c16 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -21,7 +21,7 @@ #include "color.h" #include "iccmatrices.h" #include "mytime.h" -#include "sleef.c" +#include "sleef.c" using namespace std; @@ -35,10 +35,12 @@ namespace rtengine { LUTf Color::gammatab; LUTf Color::igammatab_srgb; LUTf Color::gammatab_srgb; - // LUTf Color::igammatab_709; - // LUTf Color::gammatab_709; + // LUTf Color::igammatab_709; +// LUTf Color::gammatab_709; LUTf Color::igammatab_26_11; LUTf Color::gammatab_26_11; + LUTf Color::igammatab_24_17; + LUTf Color::gammatab_24_17a; // Wikipedia sRGB: Unlike most other RGB color spaces, the sRGB gamma cannot be expressed as a single numerical value. // The overall gamma is approximately 2.2, consisting of a linear (gamma 1.0) section near black, and a non-linear section elsewhere involving a 2.4 exponent @@ -136,10 +138,12 @@ namespace rtengine { gammatab(65536,0); igammatab_srgb(65536,0); gammatab_srgb(65536,0); - // igammatab_709(65536,0); - // gammatab_709(65536,0); + // igammatab_709(65536,0); + // gammatab_709(65536,0); igammatab_26_11(65536,0); gammatab_26_11(65536,0); + igammatab_24_17(65536,0); + gammatab_24_17a(65536,0); for (int i=0; i<65536; i++) gammatab_srgb[i] = (65535.0 * gamma2 (i/65535.0)); @@ -157,6 +161,12 @@ namespace rtengine { gammatab_26_11[i] = (65535.0 * gamma26_11 (i/65535.0)); for (int i=0; i<65536; i++) igammatab_26_11[i] = (65535.0 * igamma26_11 (i/65535.0)); + for (int i=0; i<65536; i++) { + float j = (float)i / 65535.0f; + gammatab_24_17a[i] = gamma24_17(j); + } + for (int i=0; i<65536; i++) + igammatab_24_17[i] = (65535.0 * igamma24_17 (i/65535.0)); /*FILE* f = fopen ("c.txt", "wt"); for (int i=0; i<256; i++) @@ -805,7 +815,7 @@ munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); do { inGamut=true; - //Lprov1=LL; + //Lprov1=LL; float2 sincosval = xsincosf(HH); float aprov1=Chprov1*sincosval.y; float bprov1=Chprov1*sincosval.x; @@ -934,7 +944,7 @@ munsDbgInfo->maxdhue[idx] = MAX(munsDbgInfo->maxdhue[idx], absCorrectionHue); HH+=correctlum; //hue Munsell luminance correction - correctlum = 0.0f; + correctlum = 0.0f; float2 sincosval = xsincosf(HH+correctionHuechroma); lab->a[i][j] = Chprov1*sincosval.y*327.68f; lab->b[i][j] = Chprov1*sincosval.x*327.68f; diff --git a/rtengine/color.h b/rtengine/color.h index 6301ae09e..ffbc7f8c0 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -104,6 +104,8 @@ public: // static LUTf gammatab_709; static LUTf igammatab_26_11; static LUTf gammatab_26_11; + static LUTf igammatab_24_17; + static LUTf gammatab_24_17a; // look-up tables for the simple exponential gamma static LUTf gammatab; @@ -147,7 +149,14 @@ public: static inline double igamma709 (double x) { return x <= 0.0795 ? x/4.5 : exp(log((x+0.0954)/1.0954)*2.2); } -*/ +*/ + static inline double gamma24_17 (double x) { + return x <= 0.001867 ? x*17.0 : 1.044445*exp(log(x)/2.4)-0.044445; + } + static inline double igamma24_17 (double x) { + return x <= 0.031746 ? x/17.0 : exp(log((x+0.044445)/1.044445)*2.4); + } + static inline double gamma26_11 (double x) { return x <= 0.004921 ? x*11.0 : 1.086603*exp(log(x)/2.6)-0.086603; } diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 1f0fb89a1..afb751128 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -34,6 +34,8 @@ #include "color.h" #include "../rtgui/multilangmgr.h" #include "procparams.h" +#include "sleef.c" + #ifdef _OPENMP #include @@ -48,6 +50,12 @@ namespace rtengine { #define ABS(a) ((a)<0?-(a):(a)) #define DIST(a,b) (ABS(a-b)) #define CLIREF(x) LIM(x,-200000.0f,200000.0f) // avoid overflow : do not act directly on image[] or pix[] +#define x1125(a) (a + xdivf(a, 3)) +#define x0875(a) (a - xdivf(a, 3)) +#define x0250(a) xdivf(a, 2) +#define x00625(a) xdivf(a, 4) +#define x0125(a) xdivf(a, 3) + #define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } extern const Settings* settings; @@ -1053,17 +1061,14 @@ void RawImageSource::jdl_interpolate_omp() // from "Lassus" // IEEE Trans. on Image Processing, vol. 14, pp. 2167-2178, // Dec. 2005. // Adapted to RT by Jacques Desmis 3/2013 -//TODO Tiles and OMP to reduce memory consumption and accelerate -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } -void RawImageSource::lmmse_interpolate_omp(int winw, int winh) +//TODO Tiles to reduce memory consumption +void RawImageSource::lmmse_interpolate_omp(int winw, int winh, int iterations) { int c, ii; float h0, h1, h2, h3, h4, hs; float (*rix)[6]; float (*qix)[6]; - float (*glut); - bool applyGamma=true; char *buffer; const int width=winw, height=winh; @@ -1074,7 +1079,7 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) const int w2 = 2*w1; const int w3 = 3*w1; const int w4 = 4*w1; - + int iter; h0 = 1.0f; h1 = exp( -1.0f/8.0f); h2 = exp( -4.0f/8.0f); @@ -1086,86 +1091,87 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) h2 /= hs; h3 /= hs; h4 /= hs; - + int passref; + if(iterations <=4) {iter = iterations-1;passref=0;} + else if (iterations <=6){iter=3;passref=iterations-4;} + else if (iterations <=8){iter=3;passref=iterations-6;} + bool applyGamma=true; + if(iterations==0) {applyGamma=false;iter=0;} else applyGamma=true; + if (plistener) { plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::methodstring[RAWParams::lmmse])); plistener->setProgress (0.0); } - float (*image)[4]; + float (*image)[3]; float maxdata=0.f; - // float epsil=0.00001f; unused - image = (float (*)[4]) calloc (width*height, sizeof *image); -// int curr0=0; -// int curr1=0; -// int curr2=0; + image = (float (*)[3]) calloc (width*height, sizeof *image); unsigned int a=0; +#ifdef _OPENMP +#pragma omp parallel for +#endif for (int ii=0; ii 65535.f) curr0=1; - // if(fc(ii,jj)==1 && currData > 65535.f) curr1=1; - // if(fc(ii,jj)==2 && currData > 65535.f) curr2=1; - if (currData > maxdata) maxdata=currData; + image[ii*width+jj][fc(ii,jj)] = CLIP(rawData[ii][jj]); } -// if(curr1==1 || curr2==1 || curr0==1) applyGamma=false; // LMMSE without gamma = reduce artefact in highlight - if(maxdata<65535.f) maxdata=65535.f; + maxdata=65535.f; if (applyGamma) - buffer = (char *)malloc(rr1*cc1*6*sizeof(float)+(int)(maxdata+1.f)*sizeof(float)); + buffer = (char *)malloc(rr1*cc1*6*sizeof(float)+(int)(maxdata)*sizeof(float)); else buffer = (char *)malloc(rr1*cc1*6*sizeof(float)); qix = (float (*)[6])buffer; - if (applyGamma) { - glut = (float *)(buffer + rr1*cc1*6*sizeof(float)); - for (ii=0; ii < 65536; ii++) { - float v0 = (float)ii / 65535.0f; - if (v0 <= 0.003041f) - glut[ii] = v0*12.92f; - else - glut[ii] = 1.055011f*(float)powf(v0,1.f/2.4f) - 0.055011f; - } - }// gamma sRGB - +{ if (plistener) plistener->setProgress (0.1); +} -/*#ifdef _OPENMP -#pragma omp parallel firstprivate (image,rix,qix,h0,h1,h2,h3,h4,hs) -#endif*/ -//{ +#ifdef _OPENMP +#pragma omp parallel firstprivate (image,rix,qix,h0,h1,h2,h3,h4) +#endif +{ +#ifdef _OPENMP +#pragma omp for +#endif for (int rrr=0; rrr < rr1; rrr++) for (int ccc=0, row=rrr-ba; ccc < cc1; ccc++) { int col = ccc - ba; rix = qix + rrr*cc1 + ccc; if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) { if (applyGamma) - rix[0][4] = glut[(int)image[row*width+col][FC(row,col)]]; + rix[0][4] = Color::gammatab_24_17a[image[row*width+col][FC(row,col)]]; else rix[0][4] = (float)image[row*width+col][FC(row,col)]/65535.0f; } else rix[0][4] = 0.f; } - +#ifdef _OPENMP +#pragma omp single +#endif +{ if (plistener) plistener->setProgress (0.2); +} + // G-R(B) +#ifdef _OPENMP +#pragma omp for +#endif for (int rr=2; rr < rr1-2; rr++) { // G-R(B) at R(B) location for (int cc=2+(FC(rr,2)&1); cc < cc1-2; cc+=2) { rix = qix + rr*cc1 + cc; - float v0 = 0.0625f*(rix[-w1-1][4]+rix[-w1+1][4]+rix[w1-1][4]+rix[w1+1][4]) +0.25f*rix[0][4]; + float v0 = x00625(rix[-w1-1][4]+rix[-w1+1][4]+rix[w1-1][4]+rix[w1+1][4]) +x0250(rix[0][4]); // horizontal - rix[0][0] = -0.25f*(rix[ -2][4] + rix[ 2][4])+ 0.5f*(rix[ -1][4] + rix[0][4] + rix[ 1][4]); - float Y = v0 + 0.5f*rix[0][0]; + rix[0][0] = - x0250(rix[ -2][4] + rix[ 2][4])+ xdiv2f(rix[ -1][4] + rix[0][4] + rix[ 1][4]); + float Y = v0 + xdiv2f(rix[0][0]); if (rix[0][4] > 1.75f*Y) rix[0][0] = ULIM(rix[0][0],rix[ -1][4],rix[ 1][4]); else rix[0][0] = LIM(rix[0][0],0.0f,1.0f); rix[0][0] -= rix[0][4]; // vertical - rix[0][1] = -0.25f*(rix[-w2][4] + rix[w2][4])+ 0.5f*(rix[-w1][4] + rix[0][4] + rix[w1][4]); - Y = v0 + 0.5f*rix[0][1]; + rix[0][1] = -x0250(rix[-w2][4] + rix[w2][4])+ xdiv2f(rix[-w1][4] + rix[0][4] + rix[w1][4]); + Y = v0 + xdiv2f(rix[0][1]); if (rix[0][4] > 1.75f*Y) rix[0][1] = ULIM(rix[0][1],rix[-w1][4],rix[w1][4]); else @@ -1175,26 +1181,42 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) // G-R(B) at G location for (int ccc=2+(FC(rr,3)&1); ccc < cc1-2; ccc+=2) { rix = qix + rr*cc1 + ccc; - rix[0][0] = 0.25f*(rix[ -2][4] + rix[ 2][4])- 0.5f*(rix[ -1][4] + rix[0][4] + rix[ 1][4]); - rix[0][1] = 0.25f*(rix[-w2][4] + rix[w2][4])- 0.5f*(rix[-w1][4] + rix[0][4] + rix[w1][4]); + rix[0][0] = x0250(rix[ -2][4] + rix[ 2][4])- xdiv2f(rix[ -1][4] + rix[0][4] + rix[ 1][4]); + rix[0][1] = x0250(rix[-w2][4] + rix[w2][4])- xdiv2f(rix[-w1][4] + rix[0][4] + rix[w1][4]); rix[0][0] = LIM(rix[0][0],-1.0f,0.0f) + rix[0][4]; rix[0][1] = LIM(rix[0][1],-1.0f,0.0f) + rix[0][4]; } } - +#ifdef _OPENMP +#pragma omp single +#endif +{ if (plistener) plistener->setProgress (0.25); +} + // apply low pass filter on differential colors +#ifdef _OPENMP +#pragma omp for +#endif for (int rr=4; rr < rr1-4; rr++) for (int cc=4; cc < cc1-4; cc++) { rix = qix + rr*cc1 + cc; rix[0][2] = h0*rix[0][0] + h1*(rix[ -1][0] + rix[ 1][0]) + h2*(rix[ -2][0] + rix[ 2][0]) + h3*(rix[ -3][0] + rix[ 3][0]) + h4*(rix[ -4][0] + rix[ 4][0]); rix[0][3] = h0*rix[0][1] + h1*(rix[-w1][1] + rix[w1][1]) + h2*(rix[-w2][1] + rix[w2][1]) + h3*(rix[-w3][1] + rix[w3][1]) + h4*(rix[-w4][1] + rix[w4][1]); } - +#ifdef _OPENMP +#pragma omp single +#endif +{ if (plistener) plistener->setProgress (0.3); +} + // interpolate G-R(B) at R(B) +#ifdef _OPENMP +#pragma omp for +#endif for (int rr=4; rr < rr1-4; rr++) for (int cc=4+(FC(rr,4)&1); cc < cc1-4; cc+=2) { rix = qix + rr*cc1 + cc; @@ -1249,10 +1271,18 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) // interpolated G-R(B) rix[0][4] = (xh*vv + xv*vh)/(vh + vv); } - +#ifdef _OPENMP +#pragma omp single +#endif +{ if (plistener) plistener->setProgress (0.4); +} + // copy CFA values +#ifdef _OPENMP +#pragma omp for +#endif for (int rr=0; rr < rr1; rr++) for (int cc=0, row=rr-ba; cc < cc1; cc++) { int col=cc-ba; @@ -1260,7 +1290,7 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) int c = FC(rr,cc); if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) { if (applyGamma) - rix[0][c] = glut[(int)image[row*width+col][c]]; + rix[0][c] = Color::gammatab_24_17a[image[row*width+col][c]]; else rix[0][c] = (float)image[row*width+col][c]/65535.0f; } @@ -1268,38 +1298,63 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) rix[0][c] = 0.f; if (c != 1) rix[0][1] = rix[0][c] + rix[0][4]; } - +#ifdef _OPENMP +#pragma omp single +#endif +{ if (plistener) plistener->setProgress (0.5); +} + // bilinear interpolation for R/B // interpolate R/B at G location +#ifdef _OPENMP +#pragma omp for +#endif for (int rr=1; rr < rr1-1; rr++) for (int cc=1+(FC(rr,2)&1), c=FC(rr,cc+1); cc < cc1-1; cc+=2) { rix = qix + rr*cc1 + cc; - rix[0][c] = rix[0][1] + 0.5f*(rix[ -1][c] - rix[ -1][1] + rix[ 1][c] - rix[ 1][1]); + rix[0][c] = rix[0][1] + xdiv2f(rix[ -1][c] - rix[ -1][1] + rix[ 1][c] - rix[ 1][1]); c = 2 - c; - rix[0][c] = rix[0][1]+ 0.5f*(rix[-w1][c] - rix[-w1][1] + rix[w1][c] - rix[w1][1]); + rix[0][c] = rix[0][1]+ xdiv2f(rix[-w1][c] - rix[-w1][1] + rix[w1][c] - rix[w1][1]); c = 2 - c; } - +#ifdef _OPENMP +#pragma omp single +#endif +{ if (plistener) plistener->setProgress (0.6); +} + // interpolate R/B at B/R location +#ifdef _OPENMP +#pragma omp for +#endif for (int rr=1; rr < rr1-1; rr++) for (int cc=1+(FC(rr,1)&1), c=2-FC(rr,cc); cc < cc1-1; cc+=2) { rix = qix + rr*cc1 + cc; - rix[0][c] = rix[0][1]+ 0.25f*(rix[-w1][c] - rix[-w1][1] + rix[ -1][c] - rix[ -1][1]+ rix[ 1][c] - rix[ 1][1] + rix[ w1][c] - rix[ w1][1]); + rix[0][c] = rix[0][1]+ x0250(rix[-w1][c] - rix[-w1][1] + rix[ -1][c] - rix[ -1][1]+ rix[ 1][c] - rix[ 1][1] + rix[ w1][c] - rix[ w1][1]); } - +#ifdef _OPENMP +#pragma omp single +#endif +{ if (plistener) plistener->setProgress (0.7); +} + +}// End of parallelization 1 // median filter/ - for (int pass=1; pass <= 3; pass++) { + for (int pass=0; pass < iter; pass++) { for (int c=0; c < 3; c+=2) { // Compute median(R-G) and median(B-G) int d = c + 3; for (int ii=0; ii < rr1*cc1; ii++) qix[ii][d] = qix[ii][c] - qix[ii][1]; // Apply 3x3 median filter +#ifdef _OPENMP +#pragma omp parallel for firstprivate (rix,qix) +#endif for (int rr=1; rr < rr1-1; rr++) for (int cc=1; cc < cc1-1; cc++) { float temp; @@ -1332,13 +1387,19 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) for (int cc=(FC(rr,0)&1), c=2-FC(rr,cc),d=c+3; cc < cc1; cc+=2) { rix = qix + rr*cc1 + cc; rix[0][c] = rix[0][1] + rix[0][d]; - rix[0][1] = 0.5f*(rix[0][0] - rix[0][3] + rix[0][2] - rix[0][5]); + rix[0][1] = xdiv2f(rix[0][0] - rix[0][3] + rix[0][2] - rix[0][5]); } } if (plistener) plistener->setProgress (0.8); - +#ifdef _OPENMP +#pragma omp parallel firstprivate (image,rix,qix) +#endif +{ // copy result back to image matrix +#ifdef _OPENMP +#pragma omp for +#endif for (int row=0; row < height; row++) for (int col=0, rr=row+ba; col < width; col++) { int cc = col+ba; @@ -1350,7 +1411,7 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) for (int ii=0; ii < 3; ii++) if (ii != c) { v0 = 65535.f*rix[0][ii]; - image[row*width+col][ii]=Color::igammatab_srgb[v0]; + image[row*width+col][ii]=Color::igammatab_24_17[v0]; } } else @@ -1358,9 +1419,9 @@ void RawImageSource::lmmse_interpolate_omp(int winw, int winh) if (ii != c) image[row*width+col][ii] = ((65535.0f*rix[0][ii] + 0.5f)); } - - if (plistener) plistener->setProgress (0.9); - +#ifdef _OPENMP +#pragma omp for +#endif for (int ii=0; iisetProgress (1.0); - - -//} // End of parallelization - -// Done free(buffer); free(image); + //if(iterations > 4) refinement_lassus(passref); + if(iterations > 4 && iterations <=6) refinement(passref); + else if(iterations > 6) refinement_lassus(passref); + } /*** @@ -1774,6 +1836,116 @@ void RawImageSource::nodemosaic() } } +/* + Refinement based on EECI demosaicing algorithm by L. Chang and Y.P. Tan + Paul Lee + Adapted for Rawtherapee - Jacques Desmis 04/2013 +*/ + +void RawImageSource::refinement(int PassCount) +{ + MyTime t1e,t2e; + t1e.set(); + float (*image)[3]; + int width=W; + int height=H; + int w1 = width; + int w2 = 2*w1; + + image = (float(*)[3]) calloc(W*H, sizeof *image); +#ifdef _OPENMP +#pragma omp parallel shared(image) +#endif + { +#ifdef _OPENMP +#pragma omp for +#endif + for (int i=0;isetProgressStr (M("TP_RAW_DMETHOD_PROGRESSBAR_REFINE")); + plistener->setProgress ((float)b/PassCount); + } + + /* Reinforce interpolated green pixels on RED/BLUE pixel locations */ + #ifdef _OPENMP +#pragma omp for +#endif + for (int row=2; row < height-2; row++) + for (int col=2+(FC(row,2) & 1), c=FC(row,col); col < width-2; col+=2) { + int indx = row*width+col; + float (*pix)[3]= image + indx; + double dL = 1.0/(1.0+fabs(pix[ -2][c]-pix[0][c])+fabs(pix[ 1][1]-pix[ -1][1])); + double dR = 1.0/(1.0+fabs(pix[ 2][c]-pix[0][c])+fabs(pix[ 1][1]-pix[ -1][1])); + double dU = 1.0/(1.0+fabs(pix[-w2][c]-pix[0][c])+fabs(pix[w1][1]-pix[-w1][1])); + double dD = 1.0/(1.0+fabs(pix[ w2][c]-pix[0][c])+fabs(pix[w1][1]-pix[-w1][1])); + float v0 = (float)((double)pix[0][c] + 0.5 +((double)(pix[ -1][1]-pix[ -1][c])*dL +(double)(pix[ 1][1]-pix[ 1][c])*dR +(double)(pix[-w1][1]-pix[-w1][c])*dU + + (double)(pix[ w1][1]-pix[ w1][c])*dD ) / (dL+dR+dU+dD)); + pix[0][1] = CLIP(v0); + } + + /* Reinforce interpolated red/blue pixels on GREEN pixel locations */ +#ifdef _OPENMP +#pragma omp for +#endif + for (int row=2; row < height-2; row++) + for (int col=2+(FC(row,3) & 1), c=FC(row,col+1); col < width-2; col+=2) { + int indx = row*width+col; + float (*pix)[3] = image + indx; + for (int i=0; i < 2; c=2-c, i++) { + double dL = 1.0/(1.0+fabs(pix[ -2][1]-pix[0][1])+fabs(pix[ 1][c]-pix[ -1][c])); + double dR = 1.0/(1.0+fabs(pix[ 2][1]-pix[0][1])+fabs(pix[ 1][c]-pix[ -1][c])); + double dU = 1.0/(1.0+fabs(pix[-w2][1]-pix[0][1])+fabs(pix[w1][c]-pix[-w1][c])); + double dD = 1.0/(1.0+fabs(pix[ w2][1]-pix[0][1])+fabs(pix[w1][c]-pix[-w1][c])); + float v0 = (float)((double)pix[0][1] + 0.5 -((double)(pix[ -1][1]-pix[ -1][c])*dL + (double)(pix[ 1][1]-pix[ 1][c])*dR +(double)(pix[-w1][1]-pix[-w1][c])*dU + + (double)(pix[ w1][1]-pix[ w1][c])*dD ) / (dL+dR+dU+dD)); + pix[0][c] = CLIP(v0); + } + } + + + /* Reinforce integrated red/blue pixels on BLUE/RED pixel locations */ +#ifdef _OPENMP +#pragma omp for +#endif + for (int row=2; row < height-2; row++) + for (int col=2+(FC(row,2) & 1), c=2-FC(row,col); col < width-2; col+=2) { + int indx = row*width+col; + float (*pix)[3] = image + indx; + int d = 2 - c; + double dL = 1.0/(1.0+ABS(pix[ -2][d]-pix[0][d])+ABS(pix[ 1][1]-pix[ -1][1])); + double dR = 1.0/(1.0+ABS(pix[ 2][d]-pix[0][d])+ABS(pix[ 1][1]-pix[ -1][1])); + double dU = 1.0/(1.0+ABS(pix[-w2][d]-pix[0][d])+ABS(pix[w1][1]-pix[-w1][1])); + double dD = 1.0/(1.0+ABS(pix[ w2][d]-pix[0][d])+ABS(pix[w1][1]-pix[-w1][1])); + float v0 = (float)((double)pix[0][1] + 0.5 -((double)(pix[ -1][1]-pix[ -1][c])*dL +(double)(pix[ 1][1]-pix[ 1][c])*dR +(double)(pix[-w1][1]-pix[-w1][c])*dU + + (double)(pix[ w1][1]-pix[ w1][c])*dD ) / (dL+dR+dU+dD)); + pix[0][c] = CLIP(v0); + } +} + +#ifdef _OPENMP +#pragma omp for +#endif + for (int i=0;iverbose) printf("Refinement Lee %d usec\n", t2e.etime(t1e)); +} + + // Refinement based on EECI demozaicing algorithm by L. Chang and Y.P. Tan // from "Lassus" : Luis Sanz Rodriguez, adapted by Jacques Desmis - JDC - and Oliver Duis for RawTherapee // increases the signal to noise ratio (PSNR) # +1 to +2 dB : tested with Dcraw : eg: Lighthouse + AMaZE : whitout refinement:39.96dB, with refinement:41.86 dB @@ -1781,17 +1953,17 @@ void RawImageSource::nodemosaic() // but it's relatively slow // // Should be DISABLED if it decreases image quality by increases some image noise and generates blocky edges -void RawImageSource::refinement_lassus() +void RawImageSource::refinement_lassus(int PassCount) { - const int PassCount=2; // two passes EECI refine, slow but best results... + // const int PassCount=1; - if (settings->verbose) printf("Refinement Lassus\n"); + // if (settings->verbose) printf("Refinement\n"); MyTime t1e,t2e; t1e.set(); int u=W, v=2*u, w=3*u, x=4*u, y=5*u; - float (*image)[4]; - image = (float(*)[4]) calloc(W*H, sizeof *image); + float (*image)[3]; + image = (float(*)[3]) calloc(W*H, sizeof *image); #ifdef _OPENMP #pragma omp parallel shared(image) #endif @@ -1820,21 +1992,21 @@ void RawImageSource::refinement_lassus() #endif for (int row=6; rowverbose) printf("Refinement %d usec\n", t2e.etime(t1e)); + if (settings->verbose) printf("Refinement Lassus %d usec\n", t2e.etime(t1e)); } diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 0fdb9b0d1..ef1af4d38 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -226,8 +226,9 @@ enum ProcEvent { EvDPDNbluechro=201, EvDPDNmet=202, // EvDPDNperform=201, - - NUMOFEVENTS=203 + EvDemosaicLMMSEIter=203, + NUMOFEVENTS=204 }; } #endif + diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 66ec95515..e413e2ffa 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -372,6 +372,8 @@ void ProcParams::setDefaults () { raw.dmethod = RAWParams::methodstring[RAWParams::amaze];; raw.dcb_iterations=2; raw.dcb_enhance=false; + raw.lmmse_iterations=2; + //raw.all_enhance=false; // exposure before interpolation @@ -835,6 +837,8 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, ParamsEdited* p if (!pedited || pedited->raw.dmethod) keyFile.set_string ("RAW", "Method", raw.dmethod ); if (!pedited || pedited->raw.dcbIterations) keyFile.set_integer ("RAW", "DCBIterations", raw.dcb_iterations ); if (!pedited || pedited->raw.dcbEnhance) keyFile.set_boolean ("RAW", "DCBEnhance", raw.dcb_enhance ); + if (!pedited || pedited->raw.lmmseIterations) keyFile.set_integer ("RAW", "LMMSEIterations", raw.lmmse_iterations ); + //if (!pedited || pedited->raw.allEnhance) keyFile.set_boolean ("RAW", "ALLEnhance", raw.all_enhance ); // save raw exposition @@ -1366,6 +1370,7 @@ if (keyFile.has_group ("RAW")) { if (keyFile.has_key ("RAW", "Method")) { raw.dmethod = keyFile.get_string ("RAW", "Method"); if (pedited) pedited->raw.dmethod = true; } if (keyFile.has_key ("RAW", "DCBIterations")) { raw.dcb_iterations = keyFile.get_integer("RAW", "DCBIterations"); if (pedited) pedited->raw.dcbIterations = true; } if (keyFile.has_key ("RAW", "DCBEnhance")) { raw.dcb_enhance =keyFile.get_boolean("RAW", "DCBEnhance"); if (pedited) pedited->raw.dcbEnhance = true; } + if (keyFile.has_key ("RAW", "LMMSEIterations")) { raw.lmmse_iterations = keyFile.get_integer("RAW", "LMMSEIterations"); if (pedited) pedited->raw.lmmseIterations = true; } //if (keyFile.has_key ("RAW", "ALLEnhance")) { raw.all_enhance =keyFile.get_boolean("RAW", "ALLEnhance"); if (pedited) pedited->raw.allEnhance = true; } if (keyFile.has_key ("RAW", "PreExposure")) { raw.expos =keyFile.get_double("RAW", "PreExposure"); if (pedited) pedited->raw.exPos = true; } diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 8316e8a13..d4cb47ac7 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -727,6 +727,8 @@ class RAWParams { int ccSteps; Glib::ustring dmethod; int dcb_iterations; + int lmmse_iterations; + bool dcb_enhance; //bool all_enhance; }; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 4c77ecbaa..2f3e3da00 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1076,14 +1076,14 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le } if ( raw.expos !=1 ) processRawWhitepoint(raw.expos, raw.preser); - - if(dirpyrdenoiseExpComp == INFINITY) { - LUTu aehist; int aehistcompr; - double clip=0; - int brightness, contrast, black, hlcompr, hlcomprthresh; - getAutoExpHistogram (aehist, aehistcompr); - ImProcFunctions::getAutoExp (aehist, aehistcompr, getDefGain(), clip, dirpyrdenoiseExpComp, brightness, contrast, black, hlcompr, hlcomprthresh); - } + + if(dirpyrdenoiseExpComp == INFINITY) { + LUTu aehist; int aehistcompr; + double clip=0; + int brightness, contrast, black, hlcompr, hlcomprthresh; + getAutoExpHistogram (aehist, aehistcompr); + ImProcFunctions::getAutoExp (aehist, aehistcompr, getDefGain(), clip, dirpyrdenoiseExpComp, brightness, contrast, black, hlcompr, hlcomprthresh); + } t2.set(); if( settings->verbose ) @@ -1100,7 +1100,7 @@ void RawImageSource::demosaic(const RAWParams &raw) t1.set(); bool nofast=true; if ( raw.dmethod == RAWParams::methodstring[RAWParams::hphd] ) - hphd_demosaic (); + hphd_demosaic (); else if (raw.dmethod == RAWParams::methodstring[RAWParams::vng4] ) vng4_demosaic (); else if (raw.dmethod == RAWParams::methodstring[RAWParams::ahd] ) @@ -1114,7 +1114,7 @@ void RawImageSource::demosaic(const RAWParams &raw) else if (raw.dmethod == RAWParams::methodstring[RAWParams::igv]) igv_interpolate(W,H); else if (raw.dmethod == RAWParams::methodstring[RAWParams::lmmse]) - lmmse_interpolate_omp(W,H); + lmmse_interpolate_omp(W,H,raw.lmmse_iterations); else if (raw.dmethod == RAWParams::methodstring[RAWParams::fast] ) fast_demosaic (0,0,W,H); //nodemosaic();//for testing diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 6fd5998f5..09a9d4063 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -142,7 +142,8 @@ class RawImageSource : public ImageSource { void flushRawData (); void flushRGB (); void HLRecovery_Global (HRecParams hrp); - void refinement_lassus (); + void refinement_lassus (int PassCount); + void refinement(int PassCount); bool IsrgbSourceModified() {return rgbSourceModified;} // tracks whether cached rgb output of demosaic has been modified @@ -226,7 +227,7 @@ class RawImageSource : public ImageSource { void ppg_demosaic(); void jdl_interpolate_omp(); void igv_interpolate(int winw, int winh); - void lmmse_interpolate_omp(int winw, int winh); + void lmmse_interpolate_omp(int winw, int winh, int iterations); void amaze_demosaic_RT(int winx, int winy, int winw, int winh);//Emil's code for AMaZE void fast_demosaic(int winx, int winy, int winw, int winh );//Emil's code for fast demosaicing diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index ec27b1ef7..46bd349b1 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -222,7 +222,8 @@ LUMINANCECURVE, // EvCATdatacie LUMINANCECURVE, // EvCATtonecie ALLNORAW, // EvDPDNbluechro ALLNORAW, // EvDPDNperform -ALLNORAW //EvDPDNmet +ALLNORAW, //EvDPDNmet +DEMOSAIC // EvDemosaicLMMSEIter //LUMINANCECURVE // EvCATsharpcie diff --git a/rtengine/sleef.c b/rtengine/sleef.c index b5f9ee395..1f9452768 100644 --- a/rtengine/sleef.c +++ b/rtengine/sleef.c @@ -1,6 +1,6 @@ #ifndef _SLEEFC_ #define _SLEEFC_ - + #include #include #include @@ -1191,8 +1191,8 @@ __inline float xlogf(float d) { return x; } -__inline float xexpf(float d) { - if(d<=-104.0f) return 0.0f; +__inline float xexpf(float d) { + if(d<=-104.0f) return 0.0f; int q = (int)xrintf(d * R_LN2f); float s, u; @@ -1226,4 +1226,13 @@ __inline float xdiv2f(float d) { return d; } -#endif +__inline float xdivf( float d, int n){ + if (*(int*)&d & 0x7FFFFFFF) { // if f==0 do nothing + *(int*)&d -= n << 23; // add n to the exponent + } + return d; +} + + + +#endif diff --git a/rtgui/exportpanel.cc b/rtgui/exportpanel.cc index 7e648a41f..fabaae717 100644 --- a/rtgui/exportpanel.cc +++ b/rtgui/exportpanel.cc @@ -65,6 +65,7 @@ ExportPanel::ExportPanel () : listener (NULL) { bypass_raw_ff = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_FF"))); bypass_raw_dcb_iterations = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_DCB_ITERATIONS"))); bypass_raw_dcb_enhance = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_DCB_ENHANCE"))); + bypass_raw_lmmse_iterations = Gtk::manage ( new Gtk::CheckButton (M("EXPORT_BYPASS_RAW_LMMSE_ITERATIONS"))); Gtk::HBox* hb_raw_dmethod = Gtk::manage (new Gtk::HBox ()); hb_raw_dmethod->pack_start (*Gtk::manage (new Gtk::Label ( M("EXPORT_RAW_DMETHOD") +": ")),Gtk::PACK_SHRINK, 4); @@ -94,6 +95,7 @@ ExportPanel::ExportPanel () : listener (NULL) { pack_start(*bypass_raw_dcb_iterations, Gtk::PACK_SHRINK, 4); pack_start(*bypass_raw_dcb_enhance , Gtk::PACK_SHRINK, 4); pack_start(*bypass_raw_ca , Gtk::PACK_SHRINK, 4); + pack_start(*bypass_raw_lmmse_iterations, Gtk::PACK_SHRINK, 4); pack_start(*bypass_raw_linenoise , Gtk::PACK_SHRINK, 4); pack_start(*bypass_raw_greenthresh , Gtk::PACK_SHRINK, 4); @@ -172,6 +174,7 @@ ExportPanel::ExportPanel () : listener (NULL) { bypass_raw_ccStepsConn = bypass_raw_ccSteps->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); bypass_raw_dcb_iterationsConn = bypass_raw_dcb_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); bypass_raw_dcb_enhanceConn = bypass_raw_dcb_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); + bypass_raw_lmmse_iterationsConn = bypass_raw_lmmse_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); bypass_raw_caConn = bypass_raw_ca->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); bypass_raw_linenoiseConn = bypass_raw_linenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); bypass_raw_greenthreshConn = bypass_raw_greenthresh->signal_toggled().connect (sigc::bind (sigc::mem_fun(*bypass_ALL, &Gtk::CheckButton::set_inconsistent), true)); @@ -211,6 +214,7 @@ void ExportPanel::SaveSettingsAsDefault(){ options.fastexport_bypass_raw_ccSteps = bypass_raw_ccSteps->get_active (); options.fastexport_bypass_raw_dcb_iterations = bypass_raw_dcb_iterations->get_active(); options.fastexport_bypass_raw_dcb_enhance = bypass_raw_dcb_enhance->get_active (); + options.fastexport_bypass_raw_lmmse_iterations = bypass_raw_lmmse_iterations->get_active(); options.fastexport_bypass_raw_ca = bypass_raw_ca->get_active (); options.fastexport_bypass_raw_linenoise = bypass_raw_linenoise->get_active (); options.fastexport_bypass_raw_greenthresh = bypass_raw_greenthresh->get_active (); @@ -264,6 +268,7 @@ void ExportPanel::LoadDefaultSettings(){ bypass_raw_ccSteps->set_active (options.fastexport_bypass_raw_ccSteps ); bypass_raw_dcb_iterations->set_active(options.fastexport_bypass_raw_dcb_iterations ); bypass_raw_dcb_enhance->set_active (options.fastexport_bypass_raw_dcb_enhance ); + bypass_raw_lmmse_iterations->set_active(options.fastexport_bypass_raw_lmmse_iterations ); bypass_raw_ca->set_active (options.fastexport_bypass_raw_ca ); bypass_raw_linenoise->set_active (options.fastexport_bypass_raw_linenoise ); bypass_raw_greenthresh->set_active (options.fastexport_bypass_raw_greenthresh ); @@ -333,6 +338,7 @@ void ExportPanel::bypassALL_Toggled(){ bypass_raw_ccStepsConn.block (true); bypass_raw_dcb_iterationsConn.block (true); bypass_raw_dcb_enhanceConn.block (true); + bypass_raw_lmmse_iterationsConn.block (true); bypass_raw_caConn.block (true); bypass_raw_linenoiseConn.block (true); bypass_raw_greenthreshConn.block (true); @@ -354,6 +360,7 @@ void ExportPanel::bypassALL_Toggled(){ bypass_raw_ccSteps->set_active(bypass_ALL->get_active()); bypass_raw_dcb_iterations->set_active(bypass_ALL->get_active()); bypass_raw_dcb_enhance->set_active(bypass_ALL->get_active()); + bypass_raw_lmmse_iterations->set_active(bypass_ALL->get_active()); bypass_raw_ca->set_active(bypass_ALL->get_active()); bypass_raw_linenoise->set_active(bypass_ALL->get_active()); bypass_raw_greenthresh->set_active(bypass_ALL->get_active()); @@ -373,6 +380,7 @@ void ExportPanel::bypassALL_Toggled(){ bypass_raw_ccStepsConn.block (false); bypass_raw_dcb_iterationsConn.block (false); bypass_raw_dcb_enhanceConn.block (false); + bypass_raw_lmmse_iterationsConn.block (false); bypass_raw_caConn.block (false); bypass_raw_linenoiseConn.block (false); bypass_raw_greenthreshConn.block (false); diff --git a/rtgui/exportpanel.h b/rtgui/exportpanel.h index d8e3467a9..566fb76ae 100644 --- a/rtgui/exportpanel.h +++ b/rtgui/exportpanel.h @@ -61,6 +61,7 @@ class ExportPanel : public Gtk::VBox { Gtk::CheckButton* bypass_raw_dcb_iterations; Gtk::CheckButton* bypass_raw_dcb_enhance; + Gtk::CheckButton* bypass_raw_lmmse_iterations; Gtk::CheckButton* bypass_raw_ccSteps; Gtk::CheckButton* raw_all_enhance; Gtk::CheckButton* bypass_raw_linenoise; @@ -87,6 +88,7 @@ class ExportPanel : public Gtk::VBox { sigc::connection bypass_raw_ccStepsConn ; sigc::connection bypass_raw_dcb_iterationsConn; sigc::connection bypass_raw_dcb_enhanceConn ; + sigc::connection bypass_raw_lmmse_iterationsConn; sigc::connection bypass_raw_caConn ; sigc::connection bypass_raw_linenoiseConn ; sigc::connection bypass_raw_greenthreshConn ; diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 8b90343d9..65a2ae45e 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -885,6 +885,7 @@ void FileCatalog::developRequested (std::vector tbe, bool fas if (options.fastexport_bypass_raw_ccSteps ) params.raw.ccSteps = 0; if (options.fastexport_bypass_raw_dcb_iterations ) params.raw.dcb_iterations = 0; if (options.fastexport_bypass_raw_dcb_enhance ) params.raw.dcb_enhance = false; + if (options.fastexport_bypass_raw_lmmse_iterations ) params.raw.lmmse_iterations = 0; if (options.fastexport_bypass_raw_ca ) {params.raw.ca_autocorrect =false; params.raw.cared=0; params.raw.cablue=0;} if (options.fastexport_bypass_raw_linenoise ) params.raw.linenoise = 0; if (options.fastexport_bypass_raw_greenthresh ) params.raw.greenthresh = 0; diff --git a/rtgui/options.cc b/rtgui/options.cc index ebeda3e29..0d28227a4 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -332,6 +332,7 @@ void Options::setDefaults () { fastexport_bypass_raw_ccSteps = true; fastexport_bypass_raw_dcb_iterations = true; fastexport_bypass_raw_dcb_enhance = true; + fastexport_bypass_raw_lmmse_iterations = true; fastexport_bypass_raw_ca = true; fastexport_bypass_raw_linenoise = true; fastexport_bypass_raw_greenthresh = true; @@ -716,6 +717,7 @@ if (keyFile.has_group ("Fast Export")) { if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_ccSteps" )) fastexport_bypass_raw_ccSteps = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps" ); if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_dcb_iterations")) fastexport_bypass_raw_dcb_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_dcb_iterations"); if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_dcb_enhance" )) fastexport_bypass_raw_dcb_enhance = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_dcb_enhance" ); + if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_lmmse_iterations")) fastexport_bypass_raw_lmmse_iterations = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_lmmse_iterations"); if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_ca" )) fastexport_bypass_raw_ca = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_ca" ); if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_linenoise" )) fastexport_bypass_raw_linenoise = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_linenoise" ); if (keyFile.has_key ("Fast Export", "fastexport_bypass_raw_greenthresh" )) fastexport_bypass_raw_greenthresh = keyFile.get_boolean ("Fast Export", "fastexport_bypass_raw_greenthresh" ); @@ -963,7 +965,8 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ccSteps" , fastexport_bypass_raw_ccSteps ); keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_dcb_iterations" , fastexport_bypass_raw_dcb_iterations); keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_dcb_enhance" , fastexport_bypass_raw_dcb_enhance ); - keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ca" , fastexport_bypass_raw_ca ); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_lmmse_iterations" , fastexport_bypass_raw_lmmse_iterations); + keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_ca" , fastexport_bypass_raw_ca ); keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_linenoise" , fastexport_bypass_raw_linenoise ); keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_greenthresh" , fastexport_bypass_raw_greenthresh ); keyFile.set_boolean ("Fast Export", "fastexport_bypass_raw_df" , fastexport_bypass_raw_df ); diff --git a/rtgui/options.h b/rtgui/options.h index d511019b3..2d0da00f8 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -218,6 +218,7 @@ class Options { bool fastexport_bypass_raw_ccSteps; bool fastexport_bypass_raw_dcb_iterations; bool fastexport_bypass_raw_dcb_enhance; + bool fastexport_bypass_raw_lmmse_iterations; bool fastexport_bypass_raw_ca; bool fastexport_bypass_raw_linenoise; bool fastexport_bypass_raw_greenthresh; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index f82bf52ab..52eeb36df 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -224,6 +224,8 @@ void ParamsEdited::set (bool v) { raw.dmethod = v; raw.dcbIterations = v; raw.dcbEnhance = v; + raw.lmmseIterations = v; + //raw.allEnhance = v; raw.caCorrection = v; raw.caBlue = v; @@ -465,6 +467,7 @@ void ParamsEdited::initFrom (const std::vector raw.dmethod = raw.dmethod && p.raw.dmethod == other.raw.dmethod; raw.dcbIterations = raw.dcbIterations && p.raw.dcb_iterations == other.raw.dcb_iterations; raw.dcbEnhance = raw.dcbEnhance && p.raw.dcb_enhance == other.raw.dcb_enhance; + raw.lmmseIterations = raw.lmmseIterations && p.raw.lmmse_iterations == other.raw.lmmse_iterations; //raw.allEnhance = raw.allEnhance && p.raw.all_enhance == other.raw.all_enhance; raw.caCorrection = raw.caCorrection && p.raw.ca_autocorrect == other.raw.ca_autocorrect; raw.caRed = raw.caRed && p.raw.cared == other.raw.cared; @@ -712,6 +715,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (raw.dmethod) toEdit.raw.dmethod = mods.raw.dmethod; if (raw.dcbIterations) toEdit.raw.dcb_iterations = mods.raw.dcb_iterations; if (raw.dcbEnhance) toEdit.raw.dcb_enhance = mods.raw.dcb_enhance; + if (raw.lmmseIterations) toEdit.raw.lmmse_iterations = mods.raw.lmmse_iterations; //if (raw.allEnhance) toEdit.raw.all_enhance = mods.raw.all_enhance; if (raw.caCorrection) toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; @@ -759,7 +763,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten } bool RAWParamsEdited::isUnchanged() const { - return ccSteps && dmethod && dcbIterations && dcbEnhance /*&& allEnhance*/ && caCorrection && caRed && caBlue && greenEq + return ccSteps && dmethod && dcbIterations && dcbEnhance && lmmseIterations/*&& allEnhance*/ && caCorrection && caRed && caBlue && greenEq && hotDeadPixelFilter && hotDeadPixelThresh && linenoise && darkFrame && dfAuto && ff_file && ff_AutoSelect && ff_BlurRadius && ff_BlurType && exPos && exPreser && exBlackzero && exBlackone && exBlacktwo && exBlackthree && exTwoGreen; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 74711fe4c..5c1572c17 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -390,6 +390,7 @@ class RAWParamsEdited { bool dmethod; bool dcbIterations; bool dcbEnhance; + bool lmmseIterations; //bool allEnhance; bool caCorrection; bool caRed; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index f5792f5ac..0fb14c9bc 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -101,6 +101,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { raw_dcb_iterations = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DCBITERATIONS"))); raw_dcb_enhance = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DCBENHANCE"))); //raw_all_enhance = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_ALLENHANCE"))); + raw_lmmse_iterations= Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_LMMSEITERATIONS"))); df_file = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DARKFRAMEFILE"))); df_AutoSelect = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DARKFRAMEAUTOSELECT"))); @@ -175,6 +176,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { vboxes[6]->pack_start (*raw_ccSteps, Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*raw_dcb_iterations, Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*raw_dcb_enhance, Gtk::PACK_SHRINK, 2); + vboxes[6]->pack_start (*raw_lmmse_iterations, Gtk::PACK_SHRINK, 2); //vboxes[6]->pack_start (*raw_all_enhance, Gtk::PACK_SHRINK, 2); vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0); vboxes[6]->pack_start (*raw_linenoise, Gtk::PACK_SHRINK, 2); @@ -283,6 +285,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) { raw_dcb_iterationsConn = raw_dcb_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_dcb_enhanceConn = raw_dcb_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); //raw_all_enhanceConn = raw_all_enhance->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); + raw_lmmse_iterationsConn = raw_lmmse_iterations->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_exposConn = raw_expos->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); raw_preserConn = raw_preser->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true)); @@ -353,6 +356,7 @@ void PartialPasteDlg::rawToggled () { raw_dcb_iterationsConn.block (true); raw_dcb_enhanceConn.block (true); //raw_all_enhanceConn.block (true); + raw_lmmse_iterationsConn.block (true); raw_exposConn.block (true); raw_preserConn.block (true); raw_blackConn.block (true); @@ -375,7 +379,8 @@ void PartialPasteDlg::rawToggled () { raw_ccSteps->set_active (raw->get_active ()); raw_dcb_iterations->set_active (raw->get_active ()); raw_dcb_enhance->set_active (raw->get_active ()); - //raw_all_enhance->set_active (raw->get_active ()); + raw_lmmse_iterations->set_active (raw->get_active ()); + //raw_all_enhance->set_active (raw->get_active ()); raw_expos->set_active (raw->get_active ()); raw_preser->set_active (raw->get_active ()); raw_black->set_active (raw->get_active ()); @@ -397,6 +402,7 @@ void PartialPasteDlg::rawToggled () { raw_dcb_iterationsConn.block (false); raw_dcb_enhanceConn.block (false); //raw_all_enhanceConn.block (false); + raw_lmmse_iterationsConn.block (false); raw_exposConn.block (false); raw_preserConn.block (false); raw_blackConn.block (false); @@ -630,6 +636,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param if (!raw_dcb_iterations->get_active ()) filterPE.raw.dcbIterations = falsePE.raw.dcbIterations; if (!raw_dcb_enhance->get_active ()) filterPE.raw.dcbEnhance = falsePE.raw.dcbEnhance; //if (!raw_all_enhance->get_active ()) filterPE.raw.allEnhance = falsePE.raw.allEnhance; + if (!raw_lmmse_iterations->get_active ()) filterPE.raw.lmmseIterations = falsePE.raw.lmmseIterations; if (!raw_expos->get_active ()) filterPE.raw.exPos = falsePE.raw.exPos; if (!raw_preser->get_active ()) filterPE.raw.exPreser = falsePE.raw.exPreser; diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 252590522..68512fefe 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -98,6 +98,7 @@ class PartialPasteDlg : public Gtk::Dialog { Gtk::CheckButton* raw_dcb_iterations; Gtk::CheckButton* raw_dcb_enhance; //Gtk::CheckButton* raw_all_enhance; + Gtk::CheckButton* raw_lmmse_iterations; Gtk::CheckButton* df_file; Gtk::CheckButton* df_AutoSelect; @@ -115,7 +116,7 @@ class PartialPasteDlg : public Gtk::Dialog { sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, perspectiveConn, commonTransConn; sigc::connection exifchConn, iptcConn, icmConn, gamcsconn; sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn; - sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotdeadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_dmethodConn, raw_dcb_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; //,raw_all_enhanceConn + sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotdeadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_dmethodConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; //,raw_all_enhanceConn public: PartialPasteDlg (Glib::ustring title); diff --git a/rtgui/rawprocess.cc b/rtgui/rawprocess.cc index 09ae57798..f69fb596e 100644 --- a/rtgui/rawprocess.cc +++ b/rtgui/rawprocess.cc @@ -51,6 +51,22 @@ RawProcess::RawProcess () : Gtk::VBox(), FoldableToolPanel(this) pack_start( *dcbOptions, Gtk::PACK_SHRINK, 4); pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 4 ); + lmmseOptions = Gtk::manage (new Gtk::VBox ()); + lmmseOptions->set_border_width(4); + + lmmseIterations = Gtk::manage (new Adjuster (M("TP_RAW_LMMSEITERATIONS"),0,6,1,2)); + lmmseIterations->setAdjusterListener (this); + lmmseIterations->set_tooltip_markup (M("TP_RAW_LMMSE_TOOLTIP")); + + if (lmmseIterations->delay < 1000) lmmseIterations->delay = 1000; + lmmseIterations->show(); + // dcbEnhance = Gtk::manage (new Gtk::CheckButton(M("TP_RAW_DCBENHANCE"))); + lmmseOptions->pack_start(*lmmseIterations); + // dcbOptions->pack_start(*dcbEnhance); + pack_start( *lmmseOptions, Gtk::PACK_SHRINK, 4); + pack_start( *Gtk::manage( new Gtk::HSeparator()), Gtk::PACK_SHRINK, 4 ); + + ccOptions = Gtk::manage (new Gtk::VBox ()); ccOptions->set_border_width(4); ccSteps = Gtk::manage (new Adjuster (M("TP_RAW_FALSECOLOR"),0,5,1,0 )); @@ -96,6 +112,12 @@ void RawProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEd else dcbOptions->hide(); + lmmseIterations->setValue (pp->raw.lmmse_iterations); + if (pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::lmmse]) + lmmseOptions->show(); + else + lmmseOptions->hide(); + if (pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::eahd] || pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::hphd] || pp->raw.dmethod == procparams::RAWParams::methodstring[procparams::RAWParams::vng4]) @@ -111,6 +133,7 @@ void RawProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEd dcbIterations->setEditedState ( pedited->raw.dcbIterations ? Edited : UnEdited); dcbEnhance->set_inconsistent(!pedited->raw.dcbEnhance); //allEnhance->set_inconsistent(!pedited->raw.allEnhance); + lmmseIterations->setEditedState ( pedited->raw.lmmseIterations ? Edited : UnEdited); if( !pedited->raw.dmethod ) dmethod->set_active(procparams::RAWParams::numMethods); // No name @@ -129,6 +152,7 @@ void RawProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedi pp->raw.dcb_iterations = dcbIterations->getIntValue(); pp->raw.dcb_enhance = dcbEnhance->get_active(); //pp->raw.all_enhance = allEnhance->get_active(); + pp->raw.lmmse_iterations = lmmseIterations->getIntValue(); int currentRow = dmethod->get_active_row_number(); if( currentRow>=0 && currentRow < procparams::RAWParams::numMethods) @@ -140,6 +164,7 @@ void RawProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedi pedited->raw.dcbIterations = dcbIterations->getEditedState (); pedited->raw.dcbEnhance = !dcbEnhance->get_inconsistent(); //pedited->raw.allEnhance = !allEnhance->get_inconsistent(); + pedited->raw.lmmseIterations = lmmseIterations->getEditedState (); } } @@ -148,20 +173,26 @@ void RawProcess::setBatchMode(bool batchMode) { dmethod->set_active(procparams::RAWParams::numMethods); // No name dcbOptions->hide(); + lmmseOptions->hide(); ToolPanel::setBatchMode (batchMode); ccSteps->showEditedCB (); dcbIterations->showEditedCB (); + lmmseIterations->showEditedCB (); + } void RawProcess::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { dcbIterations->setDefault( defParams->raw.dcb_iterations); + lmmseIterations->setDefault( defParams->raw.lmmse_iterations); ccSteps->setDefault (defParams->raw.ccSteps); if (pedited) { dcbIterations->setDefaultEditedState( pedited->raw.dcbIterations ? Edited : UnEdited); + lmmseIterations->setDefaultEditedState( pedited->raw.lmmseIterations ? Edited : UnEdited); ccSteps->setDefaultEditedState(pedited->raw.ccSteps ? Edited : UnEdited); }else{ dcbIterations->setDefaultEditedState( Irrelevant ); + lmmseIterations->setDefaultEditedState( Irrelevant ); ccSteps->setDefaultEditedState(Irrelevant ); } } @@ -173,7 +204,10 @@ void RawProcess::adjusterChanged (Adjuster* a, double newval) listener->panelChanged (EvDemosaicDCBIter, a->getTextValue() ); else if (a == ccSteps) listener->panelChanged (EvDemosaicFalseColorIter, a->getTextValue() ); - } + else if (a == lmmseIterations) + listener->panelChanged (EvDemosaicLMMSEIter, a->getTextValue() ); + + } } void RawProcess::methodChanged () @@ -184,6 +218,12 @@ void RawProcess::methodChanged () }else{ dcbOptions->hide(); } + if ( curSelection == procparams::RAWParams::lmmse){ + lmmseOptions->show(); + }else{ + lmmseOptions->hide(); + } + Glib::ustring methodName=""; if( curSelection>=0 && curSelection < procparams::RAWParams::numMethods) methodName = procparams::RAWParams::methodstring[curSelection]; diff --git a/rtgui/rawprocess.h b/rtgui/rawprocess.h index 817674cbe..c2c52eb47 100644 --- a/rtgui/rawprocess.h +++ b/rtgui/rawprocess.h @@ -38,6 +38,8 @@ class RawProcess : public Gtk::VBox, public AdjusterListener, public FoldableToo Gtk::CheckButton* dcbEnhance; //Gtk::VBox *allOptions; //Gtk::CheckButton* allEnhance; + Gtk::VBox *lmmseOptions; + Adjuster* lmmseIterations; bool lastDCBen; //bool lastALLen;