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;