From fd335e5c736fd682b0396ed8e1fcd26101e1a6da Mon Sep 17 00:00:00 2001 From: Emil Martinec Date: Fri, 11 Jun 2010 23:41:02 -0500 Subject: [PATCH] CFA line denoise for removing pattern noise prior to demosaic. A dialog box is added to preferences to specify the amount of line denoising to be done. Eventually the choice of line denoise threshold should be stored with other processing settings in whatever sidecar file or cache specifies such things. In addition, there are some improvements to AMaZE for better diagonal interpolation. --- rtdata/languages/English (UK) | 6 +- rtdata/languages/English (US) | 4 + rtengine/cfa_linedn_RT.cc | 423 ++++++++++++++++++++++++++++++++++ rtengine/rawimagesource.cc | 77 +++++++ rtengine/rawimagesource.h | 5 + rtengine/settings.h | 4 +- rtgui/options.cc | 15 +- rtgui/preferences.cc | 25 +- rtgui/preferences.h | 4 + 9 files changed, 555 insertions(+), 8 deletions(-) create mode 100644 rtengine/cfa_linedn_RT.cc diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 37b52708d..bb3deb741 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -1,4 +1,4 @@ -# +# # This file is part of RawTherapee. # # Copyright (c) 2004-2010 Gabor Horvath @@ -365,6 +365,10 @@ PREFERENCES_DCBENHANCE;Apply DCB enhancment step PREFERENCES_DCBITERATIONS;Number of DCB iterations #Emil's CA autocorrection PREFERENCES_CACORRECTION;Apply CA auto correction +#Emil's hot/dead pixel filter +PREFERENCES_HOTDEADPIXFILT;Apply hot/dead pixel filter +#Emil's line noise filter +PREFERENCES_LINEDENOISE;Line noise filter PREFERENCES_DEFAULTLANG;Default language PREFERENCES_DEFAULTTHEME;Default theme PREFERENCES_DEMOSAICINGALGO;Demosaicing Algorithm diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index 492a1b35c..2c9210fc5 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -367,6 +367,10 @@ PREFERENCES_DCBENHANCE;Apply DCB enhancement step PREFERENCES_DCBITERATIONS;Number of DCB iterations #Emil's CA autocorrection PREFERENCES_CACORRECTION;Apply CA auto correction +#Emil's hot/dead pixel filter +PREFERENCES_HOTDEADPIXFILT;Apply hot/dead pixel filter +#Emil's line noise filter +PREFERENCES_LINEDENOISE;Line noise filter PREFERENCES_DEFAULTLANG;Default language PREFERENCES_DEFAULTTHEME;Default theme PREFERENCES_DEMOSAICINGALGO;Demosaicing Algorithm diff --git a/rtengine/cfa_linedn_RT.cc b/rtengine/cfa_linedn_RT.cc new file mode 100644 index 000000000..151642dc0 --- /dev/null +++ b/rtengine/cfa_linedn_RT.cc @@ -0,0 +1,423 @@ +//////////////////////////////////////////////////////////////// +// +// CFA line denoise by DCT filtering +// +// copyright (c) 2008-2010 Emil Martinec +// +// +// code dated: June 7, 2010 +// +// cfa_linedn_RT.cc is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +//////////////////////////////////////////////////////////////// + + +#define TS 512 // Tile size + +#define CLASS + + +/*#include +#include +#include +#include +#include +#include +#include +#include +#include */ +#include + + +//#include "shrtdct_float.c" + + +#define SQR(x) ((x)*(x)) +//#define MIN(a,b) ((a) < (b) ? (a) : (b)) +//#define MAX(a,b) ((a) > (b) ? (a) : (b)) +//#define LIM(x,min,max) MAX(min,MIN(x,max)) +//#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) +//#define CLIP(x) LIM(x,0,65535) + +// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void RawImageSource::CLASS cfa_linedn(float noise) +{ + // local variables + int height=H, width=W; + int top, bottom, left, right, row, col; + int rr, cc, rr1, cc1, c, indx, i, j; + int ex, ey; + int verbose=1; + + float eps=1e-10; //tolerance to avoid dividing by zero + + float gauss[5] = {0.20416368871516755, 0.18017382291138087, 0.1238315368057753, 0.0662822452863612, 0.02763055063889883}; + float rolloff[8] = {0, 0.135335, 0.249352, 0.411112, 0.606531, 0.800737, 0.945959, 1}; //gaussian with sigma=3 + float window[8] = {0, .25, .75, 1, 1, .75, .25, 0}; //sine squared + float noisevar, linehvar, linevvar, coeffsq; + + float aarr[8][8], *dctblock[8]; + for (i = 0; i < 8; i++) dctblock[i] = aarr[i]; + + char *buffer; // TS*TS*16 + float (*cfain); // TS*TS*4 + float (*cfablur); // TS*TS*4 + float (*cfadiff); // TS*TS*4 + float (*cfadn); // TS*TS*4 + + double dt; + clock_t t1, t2; + + //clock_t t1_main, t2_main = 0; + + // start + //if (verbose) fprintf (stderr,_("CFA line denoise ...\n")); + //t1 = clock(); + + + // assign working space + buffer = (char *) malloc(16*TS*TS); + //merror(buffer,"cfa_linedn()"); + memset(buffer,0,16*TS*TS); + // rgb array + cfain = (float (*)) buffer; //pointers to rows of array + cfablur = (float (*)) (buffer + 4*TS*TS); + cfadiff = (float (*)) (buffer + 8*TS*TS); + cfadn = (float (*)) (buffer + 12*TS*TS); + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + if (plistener) { + plistener->setProgressStr ("Line Denoise..."); + plistener->setProgress (0.0); + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + noisevar=SQR(3*noise*65535); // _noise_ (as a fraction of saturation) is input to the algorithm + + // Main algorithm: Tile loop + for (top=0; top < height-16; top += TS-32) + for (left=0; left < width-16; left += TS-32) { + bottom = MIN( top+TS,height); + right = MIN(left+TS, width); + rr1 = bottom - top; + cc1 = right - left; + // load CFA data; data should be in linear gamma space, before white balance multipliers are applied + for (rr=0; rr < rr1; rr++) + for (row=rr+top, cc=0, indx=rr*TS+cc; cc < cc1; cc++, indx++) { + col = cc+left; + c = FC(rr,cc); + cfain[indx] = ri->data[row][col]; + } + //pad the block to a multiple of 16 on both sides + + if (cc1 < TS) { + indx=cc1 % 16; + for (i=0; i<(16-indx); i++) + for (rr=0; rrlinehvar) { + for (i=1; i<8; i++) { + coeffsq=SQR(dctblock[0][i]); + dctblock[0][i] *= coeffsq/(coeffsq+rolloff[i]*noisevar+eps); + } + } + if (noisevar>linevvar) { + for (i=1; i<8; i++) { + coeffsq=SQR(dctblock[i][0]); + dctblock[i][0] *= coeffsq/(coeffsq+rolloff[i]*noisevar+eps); + } + } + + ddct8x8s(1, dctblock); //inverse DCT + + //multiply by window fn and add to output (cfadn) + for (i=0; i<8; i++) + for (j=0; j<8; j++) { + cfadn[(rr+2*i)*TS+cc+2*j] += window[i]*window[j]*dctblock[i][j]; + } + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + // copy smoothed results back to image matrix + for (rr=16; rr < rr1-16; rr++) + for (row=rr+top, cc=16, indx=rr*TS+cc; cc < cc1-16; cc++, indx++) { + col = cc + left; + ri->data[row][col] = CLIP((int)(cfadn[indx]+ 0.5)); + } + if(plistener) plistener->setProgress(fabs((float)top/height)); + } + + // clean up + free(buffer); + + // done + /*t2 = clock(); + dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; + if (verbose) { + fprintf(stderr,_("elapsed time = %5.3fs\n"),dt); + }*/ + + +} +#undef TS + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/* + Discrete Cosine Transform Code + + Copyright(C) 1997 Takuya OOURA (email: ooura@mmm.t.u-tokyo.ac.jp). + You may use, copy, modify this code for any purpose and + without fee. You may distribute this ORIGINAL package. + */ + + +/* + Short Discrete Cosine Transform + data length :8x8 + method :row-column, radix 4 FFT + functions + ddct8x8s : 8x8 DCT + function prototypes + void ddct8x8s(int isgn, float **a); + */ + + +/* + -------- 8x8 DCT (Discrete Cosine Transform) / Inverse of DCT -------- + [definition] + Normalized 8x8 IDCT + C[k1][k2] = (1/4) * sum_j1=0^7 sum_j2=0^7 + a[j1][j2] * s[j1] * s[j2] * + cos(pi*j1*(k1+1/2)/8) * + cos(pi*j2*(k2+1/2)/8), 0<=k1<8, 0<=k2<8 + (s[0] = 1/sqrt(2), s[j] = 1, j > 0) + Normalized 8x8 DCT + C[k1][k2] = (1/4) * s[k1] * s[k2] * sum_j1=0^7 sum_j2=0^7 + a[j1][j2] * + cos(pi*(j1+1/2)*k1/8) * + cos(pi*(j2+1/2)*k2/8), 0<=k1<8, 0<=k2<8 + (s[0] = 1/sqrt(2), s[j] = 1, j > 0) + [usage] + + ddct8x8s(1, a); + + ddct8x8s(-1, a); + [parameters] + a[0...7][0...7] :input/output data (double **) + output data + a[k1][k2] = C[k1][k2], 0<=k1<8, 0<=k2<8 + */ + + +/* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */ +/* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */ +/* Wn_kR = cos(pi/2*k/n) */ +/* Wn_kI = sin(pi/2*k/n) */ +#define C8_1R 0.49039264020161522456 +#define C8_1I 0.09754516100806413392 +#define C8_2R 0.46193976625564337806 +#define C8_2I 0.19134171618254488586 +#define C8_3R 0.41573480615127261854 +#define C8_3I 0.27778511650980111237 +#define C8_4R 0.35355339059327376220 +#define W8_4R 0.70710678118654752440 + + +void RawImageSource::ddct8x8s(int isgn, float **a) +{ + int j; + float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + float xr, xi; + + if (isgn < 0) { + for (j = 0; j <= 7; j++) { + x0r = a[0][j] + a[7][j]; + x1r = a[0][j] - a[7][j]; + x0i = a[2][j] + a[5][j]; + x1i = a[2][j] - a[5][j]; + x2r = a[4][j] + a[3][j]; + x3r = a[4][j] - a[3][j]; + x2i = a[6][j] + a[1][j]; + x3i = a[6][j] - a[1][j]; + xr = x0r + x2r; + xi = x0i + x2i; + a[0][j] = C8_4R * (xr + xi); + a[4][j] = C8_4R * (xr - xi); + xr = x0r - x2r; + xi = x0i - x2i; + a[2][j] = C8_2R * xr - C8_2I * xi; + a[6][j] = C8_2R * xi + C8_2I * xr; + xr = W8_4R * (x1i - x3i); + x1i = W8_4R * (x1i + x3i); + x3i = x1i - x3r; + x1i += x3r; + x3r = x1r - xr; + x1r += xr; + a[1][j] = C8_1R * x1r - C8_1I * x1i; + a[7][j] = C8_1R * x1i + C8_1I * x1r; + a[3][j] = C8_3R * x3r - C8_3I * x3i; + a[5][j] = C8_3R * x3i + C8_3I * x3r; + } + for (j = 0; j <= 7; j++) { + x0r = a[j][0] + a[j][7]; + x1r = a[j][0] - a[j][7]; + x0i = a[j][2] + a[j][5]; + x1i = a[j][2] - a[j][5]; + x2r = a[j][4] + a[j][3]; + x3r = a[j][4] - a[j][3]; + x2i = a[j][6] + a[j][1]; + x3i = a[j][6] - a[j][1]; + xr = x0r + x2r; + xi = x0i + x2i; + a[j][0] = C8_4R * (xr + xi); + a[j][4] = C8_4R * (xr - xi); + xr = x0r - x2r; + xi = x0i - x2i; + a[j][2] = C8_2R * xr - C8_2I * xi; + a[j][6] = C8_2R * xi + C8_2I * xr; + xr = W8_4R * (x1i - x3i); + x1i = W8_4R * (x1i + x3i); + x3i = x1i - x3r; + x1i += x3r; + x3r = x1r - xr; + x1r += xr; + a[j][1] = C8_1R * x1r - C8_1I * x1i; + a[j][7] = C8_1R * x1i + C8_1I * x1r; + a[j][3] = C8_3R * x3r - C8_3I * x3i; + a[j][5] = C8_3R * x3i + C8_3I * x3r; + } + } else { + for (j = 0; j <= 7; j++) { + x1r = C8_1R * a[1][j] + C8_1I * a[7][j]; + x1i = C8_1R * a[7][j] - C8_1I * a[1][j]; + x3r = C8_3R * a[3][j] + C8_3I * a[5][j]; + x3i = C8_3R * a[5][j] - C8_3I * a[3][j]; + xr = x1r - x3r; + xi = x1i + x3i; + x1r += x3r; + x3i -= x1i; + x1i = W8_4R * (xr + xi); + x3r = W8_4R * (xr - xi); + xr = C8_2R * a[2][j] + C8_2I * a[6][j]; + xi = C8_2R * a[6][j] - C8_2I * a[2][j]; + x0r = C8_4R * (a[0][j] + a[4][j]); + x0i = C8_4R * (a[0][j] - a[4][j]); + x2r = x0r - xr; + x2i = x0i - xi; + x0r += xr; + x0i += xi; + a[0][j] = x0r + x1r; + a[7][j] = x0r - x1r; + a[2][j] = x0i + x1i; + a[5][j] = x0i - x1i; + a[4][j] = x2r - x3i; + a[3][j] = x2r + x3i; + a[6][j] = x2i - x3r; + a[1][j] = x2i + x3r; + } + for (j = 0; j <= 7; j++) { + x1r = C8_1R * a[j][1] + C8_1I * a[j][7]; + x1i = C8_1R * a[j][7] - C8_1I * a[j][1]; + x3r = C8_3R * a[j][3] + C8_3I * a[j][5]; + x3i = C8_3R * a[j][5] - C8_3I * a[j][3]; + xr = x1r - x3r; + xi = x1i + x3i; + x1r += x3r; + x3i -= x1i; + x1i = W8_4R * (xr + xi); + x3r = W8_4R * (xr - xi); + xr = C8_2R * a[j][2] + C8_2I * a[j][6]; + xi = C8_2R * a[j][6] - C8_2I * a[j][2]; + x0r = C8_4R * (a[j][0] + a[j][4]); + x0i = C8_4R * (a[j][0] - a[j][4]); + x2r = x0r - xr; + x2i = x0i - xi; + x0r += xr; + x0i += xi; + a[j][0] = x0r + x1r; + a[j][7] = x0r - x1r; + a[j][2] = x0i + x1i; + a[j][5] = x0i - x1i; + a[j][4] = x2r - x3i; + a[j][3] = x2r + x3i; + a[j][6] = x2i - x3r; + a[j][1] = x2i + x3r; + } + } +} + diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 8ef9b8a70..216ec0a1e 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -324,6 +324,59 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Image16* image, Previe isrcMutex.unlock (); } + + +void RawImageSource::cfa_clean(float thresh) //Emil's hot/dead pixel removal -- only filters egregiously impulsive pixels + { + // local variables + int rr, cc; + int gin, g[8]; + + float eps=1e-10;//tolerance to avoid dividing by zero + float p[8]; + float pixave, pixratio; + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //The cleaning algorithm starts here + + for (rr=4; rr < H-4; rr++) + for (cc=4; cc < W-4; cc++) { + + //pixel neighbor average + gin=ri->data[rr][cc]; + g[0]=ri->data[rr-2][cc-2]; + g[1]=ri->data[rr-2][cc]; + g[2]=ri->data[rr-2][cc+2]; + g[3]=ri->data[rr][cc-2]; + g[4]=ri->data[rr][cc+2]; + g[5]=ri->data[rr+2][cc-2]; + g[6]=ri->data[rr+2][cc]; + g[7]=ri->data[rr+2][cc+2]; + + pixave=(float)(g[0]+g[1]+g[2]+g[3]+g[4]+g[5]+g[6]+g[7])/8; + pixratio=MIN(gin,pixave)/(eps+MAX(gin,pixave)); + + if (pixratio > thresh) continue; + + p[0]=1/(eps+fabs(g[0]-gin)+fabs(g[0]-ri->data[rr-4][cc-4])+fabs(ri->data[rr-1][cc-1]-ri->data[rr-3][cc-3])); + p[1]=1/(eps+fabs(g[1]-gin)+fabs(g[1]-ri->data[rr-4][cc])+fabs(ri->data[rr-1][cc]-ri->data[rr-3][cc])); + p[2]=1/(eps+fabs(g[2]-gin)+fabs(g[2]-ri->data[rr-4][cc+4])+fabs(ri->data[rr-1][cc+1]-ri->data[rr-3][cc+3])); + p[3]=1/(eps+fabs(g[3]-gin)+fabs(g[3]-ri->data[rr][cc-4])+fabs(ri->data[rr][cc-1]-ri->data[rr][cc-3])); + p[4]=1/(eps+fabs(g[4]-gin)+fabs(g[4]-ri->data[rr][cc+4])+fabs(ri->data[rr][cc+1]-ri->data[rr][cc+3])); + p[5]=1/(eps+fabs(g[5]-gin)+fabs(g[5]-ri->data[rr+4][cc-4])+fabs(ri->data[rr+1][cc-1]-ri->data[rr+3][cc-3])); + p[6]=1/(eps+fabs(g[6]-gin)+fabs(g[6]-ri->data[rr+4][cc])+fabs(ri->data[rr+1][cc]-ri->data[rr+3][cc])); + p[7]=1/(eps+fabs(g[7]-gin)+fabs(g[7]-ri->data[rr+4][cc+4])+fabs(ri->data[rr+1][cc+1]-ri->data[rr+3][cc+3])); + + ri->data[rr][cc] = (int)((g[0]*p[0]+g[1]*p[1]+g[2]*p[2]+g[3]*p[3]+g[4]*p[4]+ \ + g[5]*p[5]+g[6]*p[6]+g[7]*p[7])/(p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7])); + + }//now impulsive values have been corrected + + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + } + void RawImageSource::rotateLine (unsigned short* line, unsigned short** channel, int tran, int i, int w, int h) { @@ -773,6 +826,29 @@ int RawImageSource::load (Glib::ustring fname) { */ } +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//Emil's CFA hot/dead pixel filter + + if (settings->hotdeadpix_filt) { + if (plistener) { + plistener->setProgressStr ("Hot/Dead Pixel Filter..."); + plistener->setProgress (0.0); + } + + cfa_clean(0.1); + } + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//Emil's line noise filter + + if (settings->linenoise) { + if (plistener) { + plistener->setProgressStr ("Line Denoise..."); + plistener->setProgress (0.0); + } + + cfa_linedn(0.00002*(settings->linenoise)); + } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //Emil's CA auto correction @@ -3145,6 +3221,7 @@ void RawImageSource::dcb_demosaic(int iterations, int dcb_enhance) //Emil's code for AMaZE #include "amaze_interpolate_RT.cc"//AMaZE demosaic #include "CA_correct_RT.cc"//Emil's CA auto correction +#include "cfa_linedn_RT.cc"//Emil's CA auto correction //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index bab0bafd4..e6ede29bd 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -138,6 +138,11 @@ class RawImageSource : public ImageSource { int LinEqSolve (int c, int dir, int nDim, float* pfMatr, float* pfVect, float* pfSolution);//Emil's CA auto correction void CA_correct_RT (); + void cfa_clean (float thresh);//Emil's hot/dead pixel filter + void ddct8x8s(int isgn, float **a); + + void cfa_linedn (float linenoiselevel);//Emil's line denoise + void eahd_demosaic (); void hphd_demosaic (); void vng4_demosaic (); diff --git a/rtengine/settings.h b/rtengine/settings.h index cd2dffa07..522eb8352 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -33,7 +33,9 @@ namespace rtengine { bool verbose; int dcb_iterations; // number of dcb iterations bool dcb_enhance; // whether to do image refinment - bool ca_autocorrect; // Emil's auto CA correction + bool ca_autocorrect; // Emil's CA auto correction + bool hotdeadpix_filt; // Emil's hot/dead pixel filter + int linenoise; //Emil's line denoise /** Creates a new instance of Settings. * @return a pointer to the new Settings instance. */ diff --git a/rtgui/options.cc b/rtgui/options.cc index c336bfb03..fccff63fb 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -121,6 +121,10 @@ void Options::setDefaults () { rtSettings.dualThreadEnabled = true; rtSettings.demosaicMethod = "amaze";//Emil's code for AMaZE rtSettings.ca_autocorrect = false;//Emil's CA correction + rtSettings.hotdeadpix_filt = true;//Emil's hot/dead pixel filter + + rtSettings.linenoise = 0;//Emil's line denoise + rtSettings.colorCorrectionSteps = 0; rtSettings.dcb_iterations = 2; rtSettings.dcb_enhance = true; @@ -262,6 +266,9 @@ if (keyFile.has_group ("Algorithms")) { if (keyFile.has_key ("Algorithms", "ColorCorrection")) rtSettings.colorCorrectionSteps = keyFile.get_integer ("Algorithms", "ColorCorrection"); if(keyFile.has_key("Algorithms", "DCBIterations")) rtSettings.dcb_iterations = keyFile.get_integer("Algorithms", "DCBIterations"); if(keyFile.has_key("Algorithms", "DCBEnhance")) rtSettings.dcb_enhance = keyFile.get_boolean("Algorithms", "DCBEnhance"); + if(keyFile.has_key("Algorithms", "CACorrect")) rtSettings.ca_autocorrect = keyFile.get_boolean("Algorithms", "CACorrect");//Emil's CA autocorrect + if(keyFile.has_key("Algorithms", "HotDeadPixFilt")) rtSettings.hotdeadpix_filt = keyFile.get_boolean("Algorithms", "HotDeadPixFilt");//Emil's hot/dead pixel filter + if(keyFile.has_key("Algorithms", "LineDenoise")) rtSettings.linenoise = keyFile.get_integer("Algorithms", "LineDenoise");//Emil's line denoise } if (keyFile.has_group ("Crop Settings")) { @@ -386,7 +393,9 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_integer ("Algorithms", "DCBIterations", rtSettings.dcb_iterations); keyFile.set_boolean ("Algorithms", "DCBEnhance", rtSettings.dcb_enhance); keyFile.set_boolean ("Algorithms", "CACorrect", rtSettings.ca_autocorrect);//Emil's CA correction - + keyFile.set_boolean ("Algorithms", "HotDeadPixFilt", rtSettings.hotdeadpix_filt);//Emil's hot/dead pixel filter + keyFile.set_integer ("Algorithms", "LineDenoise", rtSettings.linenoise);//Emil's line denoise + keyFile.set_integer ("Crop Settings", "DPI", cropDPI); keyFile.set_string ("Color Management", "ICCDirectory", rtSettings.iccDirectory); @@ -422,11 +431,7 @@ void Options::load () { g_mkdir_with_parents (profdir.c_str(), 511); options.saveToFile (rtdir + "/options"); } -#ifdef _WIN32 cacheBaseDir = rtdir + "/cache"; -#else - cacheBaseDir = Glib::ustring(g_get_user_cache_dir()) + "/RawTherapee"; -#endif } Glib::ustring fname = argv0+"/languages/"; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 1a3ed53b0..2da24dfcf 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -288,12 +288,28 @@ Gtk::Widget* Preferences::getProcParamsPanel () { dcbEnhance = Gtk::manage(new Gtk::CheckButton((M("PREFERENCES_DCBENHANCE")))); caAutoCorrect = Gtk::manage(new Gtk::CheckButton((M("PREFERENCES_CACORRECTION"))));//Emil's CA correction - + HotDeadPixFilt = Gtk::manage(new Gtk::CheckButton((M("PREFERENCES_HOTDEADPIXFILT"))));//Emil's hot/dead pixel filter + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //Emil's line denoise + LineDenoiseLabel = Gtk::manage(new Gtk::Label(M("PREFERENCES_LINEDENOISE")+":")); + LineDenoise = Gtk::manage(new Gtk::SpinButton ()); + LineDenoise->set_digits(0); + LineDenoise->set_increments(1, 10); + LineDenoise->set_range(0, 1000); + Gtk::HBox* hb14 = Gtk::manage(new Gtk::HBox()); + hb14->pack_start (*LineDenoiseLabel, Gtk::PACK_SHRINK, 4); + hb14->pack_start (*LineDenoise); + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + fdb->pack_start (*hb11, Gtk::PACK_SHRINK, 4); fdb->pack_start (*hb12, Gtk::PACK_SHRINK, 4); fdb->pack_start (*hb13, Gtk::PACK_SHRINK, 4); fdb->pack_start (*dcbEnhance, Gtk::PACK_SHRINK, 4); fdb->pack_start (*caAutoCorrect, Gtk::PACK_SHRINK, 4);//Emil's CA correction + fdb->pack_start (*HotDeadPixFilt, Gtk::PACK_SHRINK, 4);//Emil's hot/dead pixel filter + fdb->pack_start (*hb14, Gtk::PACK_SHRINK, 4);//Emil's line denoise + mvbpp->pack_start (*fdem, Gtk::PACK_SHRINK, 4); mvbpp->set_border_width (4); // drlab->set_size_request (drimg->get_width(), -1); @@ -722,6 +738,9 @@ void Preferences::storePreferences () { moptions.rtSettings.dcb_iterations=(int)dcbIterations->get_value(); moptions.rtSettings.dcb_enhance=dcbEnhance->get_active(); moptions.rtSettings.ca_autocorrect=caAutoCorrect->get_active();//Emil's CA correction + moptions.rtSettings.hotdeadpix_filt=HotDeadPixFilt->get_active();//Emil's hot/dead pixel filter + moptions.rtSettings.linenoise=(int)LineDenoise->get_value();//Emil's line denoise + if (sdcurrent->get_active ()) moptions.startupDir = STARTUPDIR_CURRENT; @@ -821,6 +840,10 @@ void Preferences::fillPreferences () { dcbIterations->set_sensitive(moptions.rtSettings.demosaicMethod=="dcb"); dcbIterationsLabel->set_sensitive(moptions.rtSettings.demosaicMethod=="dcb"); caAutoCorrect->set_active(moptions.rtSettings.ca_autocorrect);//Emil's CA Auto Correction + HotDeadPixFilt->set_active(moptions.rtSettings.hotdeadpix_filt);//Emil's hot/dead pixel filter + LineDenoise->set_value(moptions.rtSettings.linenoise);//Emil's line denoise + + if (moptions.startupDir==STARTUPDIR_CURRENT) sdcurrent->set_active (); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index b721cb01e..0335ff914 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -76,6 +76,10 @@ class Preferences : public Gtk::Dialog { Gtk::SpinButton* dcbIterations; Gtk::CheckButton* dcbEnhance; Gtk::CheckButton* caAutoCorrect;//Emil's CA correction + Gtk::CheckButton* HotDeadPixFilt;//Emil's hot/dead pixel filter + Gtk::Label* LineDenoiseLabel;//Emil's line denoise + Gtk::SpinButton* LineDenoise; + Gtk::FileChooserButton* iccDir; Gtk::FileChooserButton* monProfile;