diff --git a/CMakeLists.txt b/CMakeLists.txt index d56180250..6f45e5d43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,7 +245,6 @@ pkg_check_modules (LCMS REQUIRED lcms2>=2.6) pkg_check_modules (EXPAT REQUIRED expat>=2.1) pkg_check_modules (FFTW3F REQUIRED fftw3f) pkg_check_modules (IPTCDATA REQUIRED libiptcdata) -pkg_check_modules(FFTW3 fftw3) find_package (JPEG REQUIRED) find_package (PNG REQUIRED) find_package (TIFF REQUIRED) @@ -311,7 +310,7 @@ set(OOSB_FILES "${PROJECT_SOURCE_DIR}/rtdata/rawtherapee.desktop" "${PROJECT_SOU if (OUT_OF_SOURCE_BUILD) foreach(f ${OOSB_FILES}) file (REMOVE "${f}") - endforeach(f) + endforeach(f) endif () # check for generated files in the source tree which should not be there when @@ -322,7 +321,7 @@ if (OUT_OF_SOURCE_BUILD) if (EXISTS "${f}") message (SEND_ERROR "Generated \"${f}\" found inside the source tree. Please remove it as it is a relic of the old build system and prevents valid compilation now.") endif () - endforeach(f) + endforeach(f) endif () ## BEGIN: Generating AboutThisBuild.txt diff --git a/README.md b/README.md index d7ab40a5c..9dfd4c324 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,21 @@ ![RawTherapee logo](http://rawtherapee.com/images/logos/rawtherapee_logo_discuss.png) -RawTherapee is a powerful, cross-platform raw photo processing program, released under the GNU General Public License Version 3. It is written in C++ using a GTK+ front-end and a patched version of dcraw for reading raw files. It is notable for the advanced control it gives the user over the demosaicing and developing process. +RawTherapee is a powerful, cross-platform raw photo processing program, released under the [GNU General Public License Version 3](https://opensource.org/licenses/gpl-3.0.html) and written in C++ using a [GTK+](http://www.gtk.org/) front-end. It uses a patched version of [dcraw](http://www.cybercom.net/~dcoffin/dcraw/) for reading raw files, with an in-house solution which adds the highest quality support for certain camera models unsupported by dcraw and enhances the accuracy of certain raw files already supported by dcraw. It is notable for the advanced control it gives the user over the demosaicing and development process. -## Target audience and feature set +## Target audience -Rawtherapee is a free software (as in free beer) aimed at developing raw files from a broad range of camera (all files than can be decoded by *dcraw* from Dave Coffin), but can also edit standard image files (jpeg, png, tiff) and some HDR files. The targeted user base ranges from the enthusiast photographer with some basic technical knowledge in color science (it's not mandatory, but it's better if you e.g. know what a color profile is) to semi-professional users. +Rawtherapee is a [libre software](https://en.wikipedia.org/wiki/Free_software) designed for developing raw files from a broad range of digital cameras, as well as [HDR DNG](https://helpx.adobe.com/photoshop/digital-negative.html) files and non-raw image formats ([JPEG](https://en.wikipedia.org/wiki/JPEG), [TIFF](https://en.wikipedia.org/wiki/Tagged_Image_File_Format) and [PNG](https://en.wikipedia.org/wiki/Portable_Network_Graphics)). The target audience ranges from enthusiast newcomers who whish to broaden their understanding of how digital imaging works to semi-professional photographers. Knowledge in color science is not compulsory, but it is recommended that you are eager to learn and ready to read our documentation ([RawPedia](http://rawpedia.rawtherapee.com/)) as well as look up basic concepts which lie outside the scope of RawPedia, such as [color balance](https://en.wikipedia.org/wiki/Color_balance), elsewhere. -Of course, professionals can use RawTherapee (for free) too, but will probably lack some peripheral features like Digital Assets Management, printing, uploading, etc. RawTherapee is not and probably will not be an all-in-one software in the foreseeable future. But the Open Source community is sufficiently developed now to offer you all that missing peripheral features. - -The general feature set includes : -* basic file handling (move, delete, review, ranking, tagging) through thumnails -* image editing through 32 bits floating points filters (called *Tools*) that affect the whole image uniformly (by opposition to local editing, which is planned but still on the TODO list) -* export to standard 8 bits image file, with possibility to automatically load the resulting image in you favorite image editor for local adjustment +Of course, professionals may use RawTherapee too while enjoying complete freedom, but will probably lack some peripheral features such as [Digital Asset Management](https://en.wikipedia.org/wiki/Digital_asset_management), printing, uploading, etc. RawTherapee is not aimed at being an inclusive all-in-one program, and the [open-source community](https://en.wikipedia.org/wiki/Open-source_movement) is sufficiently developed by now to offer all those peripheral features in other specialized software. ## Links Website: http://rawtherapee.com/ +Features: +http://rawpedia.rawtherapee.com/Features + Official documentation: http://rawpedia.rawtherapee.com/ diff --git a/rtdata/dcpprofiles/Canon PowerShot G7 X.dcp b/rtdata/dcpprofiles/Canon PowerShot G7 X.dcp index 4f3002d5d..3a6c7800f 100644 Binary files a/rtdata/dcpprofiles/Canon PowerShot G7 X.dcp and b/rtdata/dcpprofiles/Canon PowerShot G7 X.dcp differ diff --git a/rtdata/dcpprofiles/Canon PowerShot S110.dcp b/rtdata/dcpprofiles/Canon PowerShot S110.dcp index 50c65cd8d..7f310af24 100644 Binary files a/rtdata/dcpprofiles/Canon PowerShot S110.dcp and b/rtdata/dcpprofiles/Canon PowerShot S110.dcp differ diff --git a/rtdata/dcpprofiles/Fujifilm X100T.dcp b/rtdata/dcpprofiles/Fujifilm X100T.dcp new file mode 100644 index 000000000..1fa827c5d Binary files /dev/null and b/rtdata/dcpprofiles/Fujifilm X100T.dcp differ diff --git a/rtdata/dcpprofiles/Pentax K-5 II.dcp b/rtdata/dcpprofiles/Pentax K-5 II.dcp index 22603c41f..6eef2206a 100644 Binary files a/rtdata/dcpprofiles/Pentax K-5 II.dcp and b/rtdata/dcpprofiles/Pentax K-5 II.dcp differ diff --git a/rtdata/dcpprofiles/Pentax K-5.dcp b/rtdata/dcpprofiles/Pentax K-5.dcp index f505634d9..52fbb7d85 100644 Binary files a/rtdata/dcpprofiles/Pentax K-5.dcp and b/rtdata/dcpprofiles/Pentax K-5.dcp differ diff --git a/rtdata/dcpprofiles/Pentax K10D.dcp b/rtdata/dcpprofiles/Pentax K10D.dcp index f9504b8a6..bad56c5d7 100644 Binary files a/rtdata/dcpprofiles/Pentax K10D.dcp and b/rtdata/dcpprofiles/Pentax K10D.dcp differ diff --git a/rtdata/dcpprofiles/Ricoh Pentax K-3.dcp b/rtdata/dcpprofiles/Ricoh Pentax K-3.dcp new file mode 100644 index 000000000..1eead1a2b Binary files /dev/null and b/rtdata/dcpprofiles/Ricoh Pentax K-3.dcp differ diff --git a/rtdata/dcpprofiles/Sony ILCE-7M2.dcp b/rtdata/dcpprofiles/Sony ILCE-7M2.dcp new file mode 100644 index 000000000..6d886e491 Binary files /dev/null and b/rtdata/dcpprofiles/Sony ILCE-7M2.dcp differ diff --git a/rtdata/languages/default b/rtdata/languages/default index c485f632b..cf1b3b49a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -672,6 +672,7 @@ HISTORY_MSG_436;Retinex - M - Radius HISTORY_MSG_437;Retinex - M - Method HISTORY_MSG_438;Retinex - M - Equalizer HISTORY_MSG_439;Retinex - Preview +HISTORY_MSG_440;CbDL - method HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOT;Snapshot @@ -1208,6 +1209,10 @@ TP_BWMIX_VAL;L TP_CACORRECTION_BLUE;Blue TP_CACORRECTION_LABEL;Chromatic Aberration Correction TP_CACORRECTION_RED;Red +TP_CBDL_METHOD_TOOLTIP;Choose whether the Contrast by Detail Levels tool is to be positioned after the Black-and-White tool, which makes it work in L*a*b* space, or before it, which makes it work in RGB space. +TP_CBDL_AFT;After Black-and-White +TP_CBDL_BEF;Before Black-and-White +TP_CBDL_METHOD;Process located TP_CHMIXER_BLUE;Blue channel TP_CHMIXER_GREEN;Green channel TP_CHMIXER_LABEL;Channel Mixer @@ -1613,6 +1618,7 @@ TP_PREPROCESS_NO_FOUND;None found TP_PRSHARPENING_LABEL;Post-Resize Sharpening TP_PRSHARPENING_TOOLTIP;Sharpens the image after resizing. Only works when the "Lanczos" resizing method is used. It is impossible to preview the effects of this tool. See RawPedia for usage instructions. TP_RAWCACORR_AUTO;Auto-correction +TP_RAWCACORR_CASTR;Strength TP_RAWCACORR_CABLUE;Blue TP_RAWCACORR_CARED;Red TP_RAWEXPOS_BLACKS;Black Levels diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc index eee21c18e..dd7dac228 100644 --- a/rtengine/CA_correct_RT.cc +++ b/rtengine/CA_correct_RT.cc @@ -27,10 +27,9 @@ #include "rawimagesource.h" #include "rt_math.h" -using namespace std; -using namespace rtengine; +namespace { -int RawImageSource::LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution) +bool LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution) { //============================================================================== // return 1 if system not solving, 0 if system solved @@ -77,7 +76,7 @@ int RawImageSource::LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* if( pfMatr[k * nDim + k] == 0.) { //linear system has no solution - return 1; // needs improvement !!! + return false; // needs improvement !!! } // triangulation of matrix with coefficients @@ -102,24 +101,37 @@ int RawImageSource::LinEqSolve(int nDim, double* pfMatr, double* pfVect, double* pfSolution[k] = pfSolution[k] / pfMatr[k * nDim + k]; } - return 0; + return true; } //end of linear equation solver //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +inline void pixSort(float &a, float &b) { + if (a > b) { + float temp = a; + a = b; + b = temp; + } +} -void RawImageSource::CA_correct_RT(double cared, double cablue) +} + +using namespace std; +using namespace rtengine; + +void RawImageSource::CA_correct_RT(const double cared, const double cablue, const double caautostrength) { -// multithreaded by Ingo Weyrich -#define TS 128 // Tile size -#define TSH 64 // Half Tile size -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } +// multithreaded and partly vectorized by Ingo Weyrich + constexpr int ts = 128; + constexpr int tsh = ts / 2; + //shifts to location of vertical and diagonal neighbors + constexpr int v1 = ts, v2 = 2 * ts, v3 = 3 * ts, v4 = 4 * ts; //, p1=-ts+1, p2=-2*ts+2, p3=-3*ts+3, m1=ts+1, m2=2*ts+2, m3=3*ts+3; // Test for RGB cfa for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) if(FC(i, j) == 3) { - printf("CA correction supports only RGB Color filter arrays\n"); + printf("CA correction supports only RGB Colour filter arrays\n"); return; } @@ -129,328 +141,264 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) plistener->setProgress (progress); } - bool autoCA = (cared == 0 && cablue == 0); + const bool autoCA = (cared == 0 && cablue == 0); // local variables - int width = W, height = H; + const int width = W, height = H; //temporary array to store simple interpolation of G - float (*Gtmp); - Gtmp = (float (*)) calloc ((height) * (width), sizeof * Gtmp); + float *Gtmp = (float (*)) calloc ((height) * (width), sizeof * Gtmp); // temporary array to avoid race conflicts, only every second pixel needs to be saved here - float (*RawDataTmp); - RawDataTmp = (float*) malloc( height * width * sizeof(float) / 2); + float *RawDataTmp = (float*) malloc( height * width * sizeof(float) / 2); - float blockave[2][3] = {{0, 0, 0}, {0, 0, 0}}, blocksqave[2][3] = {{0, 0, 0}, {0, 0, 0}}, blockdenom[2][3] = {{0, 0, 0}, {0, 0, 0}}, blockvar[2][3]; + float blockave[2][2] = {{0, 0}, {0, 0}}, blocksqave[2][2] = {{0, 0}, {0, 0}}, blockdenom[2][2] = {{0, 0}, {0, 0}}, blockvar[2][2]; // Because we can't break parallel processing, we need a switch do handle the errors bool processpasstwo = true; + constexpr int border = 8; + constexpr int border2 = 16; + + const int vz1 = (height + border2) % (ts - border2) == 0 ? 1 : 0; + const int hz1 = (width + border2) % (ts - border2) == 0 ? 1 : 0; + const int vblsz = ceil((float)(height + border2) / (ts - border2) + 2 + vz1); + const int hblsz = ceil((float)(width + border2) / (ts - border2) + 2 + hz1); + + char *buffer1 = (char *) calloc(vblsz * hblsz * (2 * 2 + 1), sizeof(float)); + //block CA shift values and weight assigned to block - char *buffer1; // vblsz*hblsz*(3*2+1) - float (*blockwt); // vblsz*hblsz - float (*blockshifts)[3][2]; // vblsz*hblsz*3*2 + float *blockwt = (float*)buffer1; + float (*blockshifts)[2][2] = (float (*)[2][2])(buffer1 + (vblsz * hblsz * sizeof(float))); - - const int border = 8; - const int border2 = 16; - - int vz1, hz1; - - if((height + border2) % (TS - border2) == 0) { - vz1 = 1; - } else { - vz1 = 0; - } - - if((width + border2) % (TS - border2) == 0) { - hz1 = 1; - } else { - hz1 = 0; - } - - int vblsz, hblsz; - vblsz = ceil((float)(height + border2) / (TS - border2) + 2 + vz1); - hblsz = ceil((float)(width + border2) / (TS - border2) + 2 + hz1); - - buffer1 = (char *) malloc(vblsz * hblsz * (3 * 2 + 1) * sizeof(float)); - //merror(buffer1,"CA_correct()"); - memset(buffer1, 0, vblsz * hblsz * (3 * 2 + 1)*sizeof(float)); - // block CA shifts - blockwt = (float (*)) (buffer1); - blockshifts = (float (*)[3][2]) (buffer1 + (vblsz * hblsz * sizeof(float))); - - double fitparams[3][2][16]; + double fitparams[2][2][16]; //order of 2d polynomial fit (polyord), and numpar=polyord^2 int polyord = 4, numpar = 16; - #pragma omp parallel shared(Gtmp,width,height,blockave,blocksqave,blockdenom,blockvar,blockwt,blockshifts,fitparams,polyord,numpar) + constexpr float eps = 1e-5f, eps2 = 1e-10f; //tolerance to avoid dividing by zero + + #pragma omp parallel { int progresscounter = 0; - int rrmin, rrmax, ccmin, ccmax; - int top, left, row, col; - int rr, cc, c, indx, indx1, i, j, k, m, n, dir; - //number of pixels in a tile contributing to the CA shift diagnostic - int areawt[2][3]; //direction of the CA shift in a tile int GRBdir[2][3]; - //offset data of the plaquette where the optical R/B data are sampled - int offset[2][3]; + int shifthfloor[3], shiftvfloor[3], shifthceil[3], shiftvceil[3]; - //number of tiles in the image - int vblock, hblock; - //int verbose=1; - //flag indicating success or failure of polynomial fit - int res; - //shifts to location of vertical and diagonal neighbors - const int v1 = TS, v2 = 2 * TS, v3 = 3 * TS, v4 = 4 * TS; //, p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3; - float eps = 1e-5f, eps2 = 1e-10f; //tolerance to avoid dividing by zero - - //adaptive weights for green interpolation - float wtu, wtd, wtl, wtr; //local quadratic fit to shift data within a tile - float coeff[2][3][3]; + float coeff[2][3][2]; //measured CA shift parameters for a tile - float CAshift[2][3]; + float CAshift[2][2]; //polynomial fit coefficients //residual CA shift amount within a plaquette float shifthfrac[3], shiftvfrac[3]; - //temporary storage for median filter - float temp, p[9]; - //temporary parameters for tile CA evaluation - float gdiff, deltgrb; - //interpolated G at edge of plaquette - float Ginthfloor, Ginthceil, Gint, RBint, gradwt; - //interpolated color difference at edge of plaquette - float grbdiffinthfloor, grbdiffinthceil, grbdiffint, grbdiffold; //per thread data for evaluation of block CA shift variance - float blockavethr[2][3] = {{0, 0, 0}, {0, 0, 0}}, blocksqavethr[2][3] = {{0, 0, 0}, {0, 0, 0}}, blockdenomthr[2][3] = {{0, 0, 0}, {0, 0, 0}}; //, blockvarthr[2][3]; - - //low and high pass 1D filters of G in vertical/horizontal directions - float glpfh, glpfv; - - //max allowed CA shift - const float bslim = 3.99; - //gaussians for low pass filtering of G and R/B - //static const float gaussg[5] = {0.171582, 0.15839, 0.124594, 0.083518, 0.0477063};//sig=2.5 - //static const float gaussrb[3] = {0.332406, 0.241376, 0.0924212};//sig=1.25 - - //block CA shift values and weight assigned to block - - char *buffer; // TS*TS*16 - //rgb data in a tile - float* rgb[3]; - //color differences - float (*grbdiff); // TS*TS*4 - //green interpolated to optical sample points for R/B - float (*gshift); // TS*TS*4 - //high pass filter for R/B in vertical direction - float (*rbhpfh); // TS*TS*4 - //high pass filter for R/B in horizontal direction - float (*rbhpfv); // TS*TS*4 - //low pass filter for R/B in horizontal direction - float (*rblpfh); // TS*TS*4 - //low pass filter for R/B in vertical direction - float (*rblpfv); // TS*TS*4 - //low pass filter for color differences in horizontal direction - float (*grblpfh); // TS*TS*4 - //low pass filter for color differences in vertical direction - float (*grblpfv); // TS*TS*4 - - - /* assign working space; this would not be necessary - if the algorithm is part of the larger pre-interpolation processing */ - buffer = (char *) malloc(3 * sizeof(float) * TS * TS + 8 * sizeof(float) * TS * TSH + 10 * 64 + 64); - //merror(buffer,"CA_correct()"); - memset(buffer, 0, 3 * sizeof(float)*TS * TS + 8 * sizeof(float)*TS * TSH + 10 * 64 + 64); - - char *data; - data = buffer; - -// buffers aligned to size of cacheline -// data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); + float blockavethr[2][2] = {{0, 0}, {0, 0}}, blocksqavethr[2][2] = {{0, 0}, {0, 0}}, blockdenomthr[2][2] = {{0, 0}, {0, 0}}; + // assign working space + constexpr int buffersize = 3 * sizeof(float) * ts * ts + 6 * sizeof(float) * ts * tsh + 8 * 64 + 63; + char *buffer = (char *) calloc(buffersize, 1); + char *data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64); // shift the beginning of all arrays but the first by 64 bytes to avoid cache miss conflicts on CPUs which have <=4-way associative L1-Cache - rgb[0] = (float (*)) data; - rgb[1] = (float (*)) (data + 1 * sizeof(float) * TS * TS + 1 * 64); - rgb[2] = (float (*)) (data + 2 * sizeof(float) * TS * TS + 2 * 64); - grbdiff = (float (*)) (data + 3 * sizeof(float) * TS * TS + 3 * 64); - gshift = (float (*)) (data + 3 * sizeof(float) * TS * TS + sizeof(float) * TS * TSH + 4 * 64); - rbhpfh = (float (*)) (data + 4 * sizeof(float) * TS * TS + 5 * 64); - rbhpfv = (float (*)) (data + 4 * sizeof(float) * TS * TS + sizeof(float) * TS * TSH + 6 * 64); - rblpfh = (float (*)) (data + 5 * sizeof(float) * TS * TS + 7 * 64); - rblpfv = (float (*)) (data + 5 * sizeof(float) * TS * TS + sizeof(float) * TS * TSH + 8 * 64); - grblpfh = (float (*)) (data + 6 * sizeof(float) * TS * TS + 9 * 64); - grblpfv = (float (*)) (data + 6 * sizeof(float) * TS * TS + sizeof(float) * TS * TSH + 10 * 64); + + //rgb data in a tile + float* rgb[3]; + rgb[0] = (float (*)) data; + rgb[1] = (float (*)) (data + 1 * sizeof(float) * ts * ts + 1 * 64); + rgb[2] = (float (*)) (data + 2 * sizeof(float) * ts * ts + 2 * 64); + + //high pass filter for R/B in vertical direction + float *rbhpfh = (float (*)) (data + 3 * sizeof(float) * ts * ts + 3 * 64); + //high pass filter for R/B in horizontal direction + float *rbhpfv = (float (*)) (data + 3 * sizeof(float) * ts * ts + sizeof(float) * ts * tsh + 4 * 64); + //low pass filter for R/B in horizontal direction + float *rblpfh = (float (*)) (data + 4 * sizeof(float) * ts * ts + 5 * 64); + //low pass filter for R/B in vertical direction + float *rblpfv = (float (*)) (data + 4 * sizeof(float) * ts * ts + sizeof(float) * ts * tsh + 6 * 64); + //low pass filter for colour differences in horizontal direction + float *grblpfh = (float (*)) (data + 5 * sizeof(float) * ts * ts + 7 * 64); + //low pass filter for colour differences in vertical direction + float *grblpfv = (float (*)) (data + 5 * sizeof(float) * ts * ts + sizeof(float) * ts * tsh + 8 * 64); + //colour differences + float *grbdiff = rbhpfh; // there is no overlap in buffer usage => share + //green interpolated to optical sample points for R/B + float *gshift = rbhpfv; // there is no overlap in buffer usage => share if (autoCA) { - // Main algorithm: Tile loop + // Main algorithm: Tile loop calculating correction parameters per tile #pragma omp for collapse(2) schedule(dynamic) nowait - for (top = -border ; top < height; top += TS - border2) - for (left = -border; left < width; left += TS - border2) { - vblock = ((top + border) / (TS - border2)) + 1; - hblock = ((left + border) / (TS - border2)) + 1; - int bottom = min(top + TS, height + border); - int right = min(left + TS, width + border); - int rr1 = bottom - top; - int cc1 = right - left; - - //t1_init = clock(); - if (top < 0) { - rrmin = border; - } else { - rrmin = 0; - } - - if (left < 0) { - ccmin = border; - } else { - ccmin = 0; - } - - if (bottom > height) { - rrmax = height - top; - } else { - rrmax = rr1; - } - - if (right > width) { - ccmax = width - left; - } else { - ccmax = cc1; - } + for (int top = -border ; top < height; top += ts - border2) + for (int left = -border; left < width; left += ts - border2) { + const int vblock = ((top + border) / (ts - border2)) + 1; + const int hblock = ((left + border) / (ts - border2)) + 1; + const int bottom = min(top + ts, height + border); + const int right = min(left + ts, width + border); + const int rr1 = bottom - top; + const int cc1 = right - left; + const int rrmin = top < 0 ? border : 0; + const int rrmax = bottom > height ? height - top : rr1; + const int ccmin = left < 0 ? border : 0; + const int ccmax = right > width ? width - left : cc1; // rgb from input CFA data - // rgb values should be floating point number between 0 and 1 + // rgb values should be floating point numbers between 0 and 1 // after white balance multipliers are applied - for (rr = rrmin; rr < rrmax; rr++) - for (row = rr + top, cc = ccmin; cc < ccmax; cc++) { - col = cc + left; - c = FC(rr, cc); - indx = row * width + col; - indx1 = rr * TS + cc; + for (int rr = rrmin; rr < rrmax; rr++) + for (int row = rr + top, cc = ccmin; cc < ccmax; cc++) { + int col = cc + left; + int c = FC(rr, cc); + int indx = row * width + col; + int indx1 = rr * ts + cc; rgb[c][indx1] = (rawData[row][col]) / 65535.0f; - //rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation } // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //fill borders if (rrmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = ccmin; cc < ccmax; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + cc] = rgb[c][(border2 - rr) * TS + cc]; + for (int rr = 0; rr < border; rr++) + for (int cc = ccmin; cc < ccmax; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + cc] = rgb[c][(border2 - rr) * ts + cc]; } } if (rrmax < rr1) { - for (rr = 0; rr < border; rr++) - for (cc = ccmin; cc < ccmax; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + cc] = (rawData[(height - rr - 2)][left + cc]) / 65535.0f; - //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+left+cc][c])/65535.0f;//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = ccmin; cc < ccmax; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + cc] = (rawData[(height - rr - 2)][left + cc]) / 65535.0f; } } if (ccmin > 0) { - for (rr = rrmin; rr < rrmax; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + cc] = rgb[c][rr * TS + border2 - cc]; + for (int rr = rrmin; rr < rrmax; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + cc] = rgb[c][rr * ts + border2 - cc]; } } if (ccmax < cc1) { - for (rr = rrmin; rr < rrmax; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + ccmax + cc] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.0f; - //rgb[rr*TS+ccmax+cc][c] = (image[(top+rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation + for (int rr = rrmin; rr < rrmax; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + ccmax + cc] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.0f; } } //also, fill the image corners if (rrmin > 0 && ccmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rr)*TS + cc] = (rawData[border2 - rr][border2 - cc]) / 65535.0f; - //rgb[(rr)*TS+cc][c] = (rgb[(border2-rr)*TS+(border2-cc)][c]);//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rr)*ts + cc] = (rawData[border2 - rr][border2 - cc]) / 65535.0f; } } if (rrmax < rr1 && ccmax < cc1) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + ccmax + cc] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.0f; - //rgb[(rrmax+rr)*TS+ccmax+cc][c] = (image[(height-rr-2)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + ccmax + cc] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.0f; } } if (rrmin > 0 && ccmax < cc1) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rr)*TS + ccmax + cc] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.0f; - //rgb[(rr)*TS+ccmax+cc][c] = (image[(border2-rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rr)*ts + ccmax + cc] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.0f; } } if (rrmax < rr1 && ccmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + cc] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.0f; - //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(border2-cc)][c])/65535.0f;//for dcraw implementation + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + cc] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.0f; } } //end of border fill // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - for (j = 0; j < 2; j++) - for (k = 0; k < 3; k++) - for (c = 0; c < 3; c += 2) { - coeff[j][k][c] = 0; - } - //end of initialization - for (rr = 3; rr < rr1 - 3; rr++) - for (row = rr + top, cc = 3, indx = rr * TS + cc; cc < cc1 - 3; cc++, indx++) { - col = cc + left; - c = FC(rr, cc); +#ifdef __SSE2__ + vfloat onev = F2V(1.f); + vfloat epsv = F2V(eps); +#endif + for (int rr = 3; rr < rr1 - 3; rr++) { + int row = rr + top; + int cc = 3 + (FC(rr,3) & 1); + int indx = rr * ts + cc; + int c = FC(rr,cc); +#ifdef __SSE2__ + for (; cc < cc1 - 9; cc+=8, indx+=8) { + //compute directional weights using image gradients + vfloat wtuv = onev / SQRV(epsv + vabsf(LC2VFU(rgb[1][indx + v1]) - LC2VFU(rgb[1][indx - v1])) + vabsf(LC2VFU(rgb[c][indx]) - LC2VFU(rgb[c][indx - v2])) + vabsf(LC2VFU(rgb[1][indx - v1]) - LC2VFU(rgb[1][indx - v3]))); + vfloat wtdv = onev / SQRV(epsv + vabsf(LC2VFU(rgb[1][indx - v1]) - LC2VFU(rgb[1][indx + v1])) + vabsf(LC2VFU(rgb[c][indx]) - LC2VFU(rgb[c][indx + v2])) + vabsf(LC2VFU(rgb[1][indx + v1]) - LC2VFU(rgb[1][indx + v3]))); + vfloat wtlv = onev / SQRV(epsv + vabsf(LC2VFU(rgb[1][indx + 1]) - LC2VFU(rgb[1][indx - 1])) + vabsf(LC2VFU(rgb[c][indx]) - LC2VFU(rgb[c][indx - 2])) + vabsf(LC2VFU(rgb[1][indx - 1]) - LC2VFU(rgb[1][indx - 3]))); + vfloat wtrv = onev / SQRV(epsv + vabsf(LC2VFU(rgb[1][indx - 1]) - LC2VFU(rgb[1][indx + 1])) + vabsf(LC2VFU(rgb[c][indx]) - LC2VFU(rgb[c][indx + 2])) + vabsf(LC2VFU(rgb[1][indx + 1]) - LC2VFU(rgb[1][indx + 3]))); - if (c != 1) { - //compute directional weights using image gradients - wtu = 1.0 / SQR(eps + fabsf(rgb[1][indx + v1] - rgb[1][indx - v1]) + fabsf(rgb[c][indx] - rgb[c][indx - v2]) + fabsf(rgb[1][indx - v1] - rgb[1][indx - v3])); - wtd = 1.0 / SQR(eps + fabsf(rgb[1][indx - v1] - rgb[1][indx + v1]) + fabsf(rgb[c][indx] - rgb[c][indx + v2]) + fabsf(rgb[1][indx + v1] - rgb[1][indx + v3])); - wtl = 1.0 / SQR(eps + fabsf(rgb[1][indx + 1] - rgb[1][indx - 1]) + fabsf(rgb[c][indx] - rgb[c][indx - 2]) + fabsf(rgb[1][indx - 1] - rgb[1][indx - 3])); - wtr = 1.0 / SQR(eps + fabsf(rgb[1][indx - 1] - rgb[1][indx + 1]) + fabsf(rgb[c][indx] - rgb[c][indx + 2]) + fabsf(rgb[1][indx + 1] - rgb[1][indx + 3])); + //store in rgb array the interpolated G value at R/B grid points using directional weighted average + STC2VFU(rgb[1][indx], (wtuv * LC2VFU(rgb[1][indx - v1]) + wtdv * LC2VFU(rgb[1][indx + v1]) + wtlv * LC2VFU(rgb[1][indx - 1]) + wtrv * LC2VFU(rgb[1][indx + 1])) / (wtuv + wtdv + wtlv + wtrv)); + } - //store in rgb array the interpolated G value at R/B grid points using directional weighted average - rgb[1][indx] = (wtu * rgb[1][indx - v1] + wtd * rgb[1][indx + v1] + wtl * rgb[1][indx - 1] + wtr * rgb[1][indx + 1]) / (wtu + wtd + wtl + wtr); - } +#endif + for (; cc < cc1 - 3; cc+=2, indx+=2) { + //compute directional weights using image gradients + float wtu = 1.f / SQR(eps + fabsf(rgb[1][indx + v1] - rgb[1][indx - v1]) + fabsf(rgb[c][indx] - rgb[c][indx - v2]) + fabsf(rgb[1][indx - v1] - rgb[1][indx - v3])); + float wtd = 1.f / SQR(eps + fabsf(rgb[1][indx - v1] - rgb[1][indx + v1]) + fabsf(rgb[c][indx] - rgb[c][indx + v2]) + fabsf(rgb[1][indx + v1] - rgb[1][indx + v3])); + float wtl = 1.f / SQR(eps + fabsf(rgb[1][indx + 1] - rgb[1][indx - 1]) + fabsf(rgb[c][indx] - rgb[c][indx - 2]) + fabsf(rgb[1][indx - 1] - rgb[1][indx - 3])); + float wtr = 1.f / SQR(eps + fabsf(rgb[1][indx - 1] - rgb[1][indx + 1]) + fabsf(rgb[c][indx] - rgb[c][indx + 2]) + fabsf(rgb[1][indx + 1] - rgb[1][indx + 3])); - if (row > -1 && row < height && col > -1 && col < width) { + //store in rgb array the interpolated G value at R/B grid points using directional weighted average + rgb[1][indx] = (wtu * rgb[1][indx - v1] + wtd * rgb[1][indx + v1] + wtl * rgb[1][indx - 1] + wtr * rgb[1][indx + 1]) / (wtu + wtd + wtl + wtr); + } + + if (row > -1 && row < height) { + for(int col = max(left + 3, 0), indx = rr * ts + 3 - (left < 0 ? (left+3) : 0); col < min(cc1 + left - 3, width); col++, indx++) { Gtmp[row * width + col] = rgb[1][indx]; } } + } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#ifdef __SSE2__ + vfloat zd25v = F2V(0.25f); +#endif + for (int rr = 4; rr < rr1 - 4; rr++) { + int cc = 4 + (FC(rr, 2) & 1), indx = rr * ts + cc, c = FC(rr, cc); +#ifdef __SSE2__ + for (; cc < cc1 - 10; cc += 8, indx += 8) { + vfloat rgb1v = LC2VFU(rgb[1][indx]); + vfloat rgbcv = LC2VFU(rgb[c][indx]); + vfloat temp1v = vabsf(vabsf((rgb1v - rgbcv) - (LC2VFU(rgb[1][indx + v4]) - LC2VFU(rgb[c][indx + v4]))) + + vabsf(LC2VFU(rgb[1][indx - v4]) - LC2VFU(rgb[c][indx - v4]) - rgb1v + rgbcv) - + vabsf(LC2VFU(rgb[1][indx - v4]) - LC2VFU(rgb[c][indx - v4]) - LC2VFU(rgb[1][indx + v4]) + LC2VFU(rgb[c][indx + v4]))); + STVFU(rbhpfv[indx >> 1], temp1v); + vfloat temp2v = vabsf(vabsf((rgb1v - rgbcv) - (LC2VFU(rgb[1][indx + 4]) - LC2VFU(rgb[c][indx + 4]))) + + vabsf(LC2VFU(rgb[1][indx - 4]) - LC2VFU(rgb[c][indx - 4]) - rgb1v + rgbcv) - + vabsf(LC2VFU(rgb[1][indx - 4]) - LC2VFU(rgb[c][indx - 4]) - LC2VFU(rgb[1][indx + 4]) + LC2VFU(rgb[c][indx + 4]))); + STVFU(rbhpfh[indx >> 1], temp2v); - for (rr = 4; rr < rr1 - 4; rr++) - for (cc = 4 + (FC(rr, 2) & 1), indx = rr * TS + cc, c = FC(rr, cc); cc < cc1 - 4; cc += 2, indx += 2) { - + //low and high pass 1D filters of G in vertical/horizontal directions + rgb1v = vmul2f(rgb1v); + vfloat glpfvv = zd25v * (rgb1v + LC2VFU(rgb[1][indx + v2]) + LC2VFU(rgb[1][indx - v2])); + vfloat glpfhv = zd25v * (rgb1v + LC2VFU(rgb[1][indx + 2]) + LC2VFU(rgb[1][indx - 2])); + rgbcv = vmul2f(rgbcv); + STVFU(rblpfv[indx >> 1], epsv + vabsf(glpfvv - zd25v * (rgbcv + LC2VFU(rgb[c][indx + v2]) + LC2VFU(rgb[c][indx - v2])))); + STVFU(rblpfh[indx >> 1], epsv + vabsf(glpfhv - zd25v * (rgbcv + LC2VFU(rgb[c][indx + 2]) + LC2VFU(rgb[c][indx - 2])))); + STVFU(grblpfv[indx >> 1], glpfvv + zd25v * (rgbcv + LC2VFU(rgb[c][indx + v2]) + LC2VFU(rgb[c][indx - v2]))); + STVFU(grblpfh[indx >> 1], glpfhv + zd25v * (rgbcv + LC2VFU(rgb[c][indx + 2]) + LC2VFU(rgb[c][indx - 2]))); + } +#endif + for (; cc < cc1 - 4; cc += 2, indx += 2) { rbhpfv[indx >> 1] = fabsf(fabsf((rgb[1][indx] - rgb[c][indx]) - (rgb[1][indx + v4] - rgb[c][indx + v4])) + fabsf((rgb[1][indx - v4] - rgb[c][indx - v4]) - (rgb[1][indx] - rgb[c][indx])) - fabsf((rgb[1][indx - v4] - rgb[c][indx - v4]) - (rgb[1][indx + v4] - rgb[c][indx + v4]))); @@ -458,176 +406,148 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) fabsf((rgb[1][indx - 4] - rgb[c][indx - 4]) - (rgb[1][indx] - rgb[c][indx])) - fabsf((rgb[1][indx - 4] - rgb[c][indx - 4]) - (rgb[1][indx + 4] - rgb[c][indx + 4]))); - /*ghpfv = fabsf(fabsf(rgb[indx][1]-rgb[indx+v4][1])+fabsf(rgb[indx][1]-rgb[indx-v4][1]) - - fabsf(rgb[indx+v4][1]-rgb[indx-v4][1])); - ghpfh = fabsf(fabsf(rgb[indx][1]-rgb[indx+4][1])+fabsf(rgb[indx][1]-rgb[indx-4][1]) - - fabsf(rgb[indx+4][1]-rgb[indx-4][1])); - rbhpfv[indx] = fabsf(ghpfv - fabsf(fabsf(rgb[indx][c]-rgb[indx+v4][c])+fabsf(rgb[indx][c]-rgb[indx-v4][c]) - - fabsf(rgb[indx+v4][c]-rgb[indx-v4][c]))); - rbhpfh[indx] = fabsf(ghpfh - fabsf(fabsf(rgb[indx][c]-rgb[indx+4][c])+fabsf(rgb[indx][c]-rgb[indx-4][c]) - - fabsf(rgb[indx+4][c]-rgb[indx-4][c])));*/ - - glpfv = 0.25 * (2.0 * rgb[1][indx] + rgb[1][indx + v2] + rgb[1][indx - v2]); - glpfh = 0.25 * (2.0 * rgb[1][indx] + rgb[1][indx + 2] + rgb[1][indx - 2]); - rblpfv[indx >> 1] = eps + fabsf(glpfv - 0.25 * (2.0 * rgb[c][indx] + rgb[c][indx + v2] + rgb[c][indx - v2])); - rblpfh[indx >> 1] = eps + fabsf(glpfh - 0.25 * (2.0 * rgb[c][indx] + rgb[c][indx + 2] + rgb[c][indx - 2])); - grblpfv[indx >> 1] = glpfv + 0.25 * (2.0 * rgb[c][indx] + rgb[c][indx + v2] + rgb[c][indx - v2]); - grblpfh[indx >> 1] = glpfh + 0.25 * (2.0 * rgb[c][indx] + rgb[c][indx + 2] + rgb[c][indx - 2]); + //low and high pass 1D filters of G in vertical/horizontal directions + float glpfv = 0.25f * (2.f * rgb[1][indx] + rgb[1][indx + v2] + rgb[1][indx - v2]); + float glpfh = 0.25f * (2.f * rgb[1][indx] + rgb[1][indx + 2] + rgb[1][indx - 2]); + rblpfv[indx >> 1] = eps + fabsf(glpfv - 0.25f * (2.f * rgb[c][indx] + rgb[c][indx + v2] + rgb[c][indx - v2])); + rblpfh[indx >> 1] = eps + fabsf(glpfh - 0.25f * (2.f * rgb[c][indx] + rgb[c][indx + 2] + rgb[c][indx - 2])); + grblpfv[indx >> 1] = glpfv + 0.25f * (2.f * rgb[c][indx] + rgb[c][indx + v2] + rgb[c][indx - v2]); + grblpfh[indx >> 1] = glpfh + 0.25f * (2.f * rgb[c][indx] + rgb[c][indx + 2] + rgb[c][indx - 2]); } + } - areawt[0][0] = areawt[1][0] = 1; - areawt[0][2] = areawt[1][2] = 1; + for (int dir = 0; dir < 2; dir++) { + for (int k = 0; k < 3; k++) { + for (int c = 0; c < 2; c++) { + coeff[dir][k][c] = 0; + } + } + } - // along line segments, find the point along each segment that minimizes the color variance +#ifdef __SSE2__ + vfloat zd3125v = F2V(0.3125f); + vfloat zd09375v = F2V(0.09375f); + vfloat zd1v = F2V(0.1f); + vfloat zd125v = F2V(0.125f); +#endif + + // along line segments, find the point along each segment that minimizes the colour variance // averaged over the tile; evaluate for up/down and left/right away from R/B grid point - for (rr = 8; rr < rr1 - 8; rr++) - for (cc = 8 + (FC(rr, 2) & 1), indx = rr * TS + cc, c = FC(rr, cc); cc < cc1 - 8; cc += 2, indx += 2) { + for (int rr = 8; rr < rr1 - 8; rr++) { + int cc = 8 + (FC(rr, 2) & 1); + int indx = rr * ts + cc; + int c = FC(rr, cc); +#ifdef __SSE2__ + vfloat coeff00v = ZEROV; + vfloat coeff01v = ZEROV; + vfloat coeff02v = ZEROV; + vfloat coeff10v = ZEROV; + vfloat coeff11v = ZEROV; + vfloat coeff12v = ZEROV; + for (; cc < cc1 - 14; cc += 8, indx += 8) { -// areawt[0][c]=areawt[1][c]=0; - - //in linear interpolation, color differences are a quadratic function of interpolation position; - //solve for the interpolation position that minimizes color difference variance over the tile + //in linear interpolation, colour differences are a quadratic function of interpolation position; + //solve for the interpolation position that minimizes colour difference variance over the tile //vertical - gdiff = 0.3125 * (rgb[1][indx + TS] - rgb[1][indx - TS]) + 0.09375 * (rgb[1][indx + TS + 1] - rgb[1][indx - TS + 1] + rgb[1][indx + TS - 1] - rgb[1][indx - TS - 1]); - deltgrb = (rgb[c][indx] - rgb[1][indx]); + vfloat gdiffv = zd3125v * (LC2VFU(rgb[1][indx + ts]) - LC2VFU(rgb[1][indx - ts])) + zd09375v * (LC2VFU(rgb[1][indx + ts + 1]) - LC2VFU(rgb[1][indx - ts + 1]) + LC2VFU(rgb[1][indx + ts - 1]) - LC2VFU(rgb[1][indx - ts - 1])); + vfloat deltgrbv = LC2VFU(rgb[c][indx]) - LC2VFU(rgb[1][indx]); - gradwt = fabsf(0.25 * rbhpfv[indx >> 1] + 0.125 * (rbhpfv[(indx >> 1) + 1] + rbhpfv[(indx >> 1) - 1]) ) * (grblpfv[(indx >> 1) - v1] + grblpfv[(indx >> 1) + v1]) / (eps + 0.1 * grblpfv[(indx >> 1) - v1] + rblpfv[(indx >> 1) - v1] + 0.1 * grblpfv[(indx >> 1) + v1] + rblpfv[(indx >> 1) + v1]); + vfloat gradwtv = vabsf(zd25v * LVFU(rbhpfv[indx >> 1]) + zd125v * (LVFU(rbhpfv[(indx >> 1) + 1]) + LVFU(rbhpfv[(indx >> 1) - 1])) ) * (LVFU(grblpfv[(indx >> 1) - v1]) + LVFU(grblpfv[(indx >> 1) + v1])) / (epsv + zd1v * (LVFU(grblpfv[(indx >> 1) - v1]) + LVFU(grblpfv[(indx >> 1) + v1])) + LVFU(rblpfv[(indx >> 1) - v1]) + LVFU(rblpfv[(indx >> 1) + v1])); - coeff[0][0][c] += gradwt * deltgrb * deltgrb; - coeff[0][1][c] += gradwt * gdiff * deltgrb; - coeff[0][2][c] += gradwt * gdiff * gdiff; -// areawt[0][c]+=1; + coeff00v += gradwtv * deltgrbv * deltgrbv; + coeff01v += gradwtv * gdiffv * deltgrbv; + coeff02v += gradwtv * gdiffv * gdiffv; //horizontal - gdiff = 0.3125 * (rgb[1][indx + 1] - rgb[1][indx - 1]) + 0.09375 * (rgb[1][indx + 1 + TS] - rgb[1][indx - 1 + TS] + rgb[1][indx + 1 - TS] - rgb[1][indx - 1 - TS]); - deltgrb = (rgb[c][indx] - rgb[1][indx]); + gdiffv = zd3125v * (LC2VFU(rgb[1][indx + 1]) - LC2VFU(rgb[1][indx - 1])) + zd09375v * (LC2VFU(rgb[1][indx + 1 + ts]) - LC2VFU(rgb[1][indx - 1 + ts]) + LC2VFU(rgb[1][indx + 1 - ts]) - LC2VFU(rgb[1][indx - 1 - ts])); - gradwt = fabsf(0.25 * rbhpfh[indx >> 1] + 0.125 * (rbhpfh[(indx >> 1) + v1] + rbhpfh[(indx >> 1) - v1]) ) * (grblpfh[(indx >> 1) - 1] + grblpfh[(indx >> 1) + 1]) / (eps + 0.1 * grblpfh[(indx >> 1) - 1] + rblpfh[(indx >> 1) - 1] + 0.1 * grblpfh[(indx >> 1) + 1] + rblpfh[(indx >> 1) + 1]); + gradwtv = vabsf(zd25v * LVFU(rbhpfh[indx >> 1]) + zd125v * (LVFU(rbhpfh[(indx >> 1) + v1]) + LVFU(rbhpfh[(indx >> 1) - v1])) ) * (LVFU(grblpfh[(indx >> 1) - 1]) + LVFU(grblpfh[(indx >> 1) + 1])) / (epsv + zd1v * (LVFU(grblpfh[(indx >> 1) - 1]) + LVFU(grblpfh[(indx >> 1) + 1])) + LVFU(rblpfh[(indx >> 1) - 1]) + LVFU(rblpfh[(indx >> 1) + 1])); - coeff[1][0][c] += gradwt * deltgrb * deltgrb; - coeff[1][1][c] += gradwt * gdiff * deltgrb; - coeff[1][2][c] += gradwt * gdiff * gdiff; -// areawt[1][c]+=1; + coeff10v += gradwtv * deltgrbv * deltgrbv; + coeff11v += gradwtv * gdiffv * deltgrbv; + coeff12v += gradwtv * gdiffv * gdiffv; // In Mathematica, // f[x_]=Expand[Total[Flatten[ // ((1-x) RotateLeft[Gint,shift1]+x RotateLeft[Gint,shift2]-cfapad)^2[[dv;;-1;;2,dh;;-1;;2]]]]]; // extremum = -.5Coefficient[f[x],x]/Coefficient[f[x],x^2] } + coeff[0][0][c>>1] += vhadd(coeff00v); + coeff[0][1][c>>1] += vhadd(coeff01v); + coeff[0][2][c>>1] += vhadd(coeff02v); + coeff[1][0][c>>1] += vhadd(coeff10v); + coeff[1][1][c>>1] += vhadd(coeff11v); + coeff[1][2][c>>1] += vhadd(coeff12v); - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - /* - for (rr=4; rr < rr1-4; rr++) - for (cc=4+(FC(rr,2)&1), indx=rr*TS+cc, c = FC(rr,cc); cc < cc1-4; cc+=2, indx+=2) { +#endif + for (; cc < cc1 - 8; cc += 2, indx += 2) { - - rbhpfv[indx] = SQR(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+v4][1]-rgb[indx+v4][c])) + - fabs((rgb[indx-v4][1]-rgb[indx-v4][c])-(rgb[indx][1]-rgb[indx][c])) - - fabs((rgb[indx-v4][1]-rgb[indx-v4][c])-(rgb[indx+v4][1]-rgb[indx+v4][c]))); - rbhpfh[indx] = SQR(fabs((rgb[indx][1]-rgb[indx][c])-(rgb[indx+4][1]-rgb[indx+4][c])) + - fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx][1]-rgb[indx][c])) - - fabs((rgb[indx-4][1]-rgb[indx-4][c])-(rgb[indx+4][1]-rgb[indx+4][c]))); - - - glpfv = 0.25*(2*rgb[indx][1]+rgb[indx+v2][1]+rgb[indx-v2][1]); - glpfh = 0.25*(2*rgb[indx][1]+rgb[indx+2][1]+rgb[indx-2][1]); - rblpfv[indx] = eps+fabs(glpfv - 0.25*(2*rgb[indx][c]+rgb[indx+v2][c]+rgb[indx-v2][c])); - rblpfh[indx] = eps+fabs(glpfh - 0.25*(2*rgb[indx][c]+rgb[indx+2][c]+rgb[indx-2][c])); - grblpfv[indx] = glpfv + 0.25*(2*rgb[indx][c]+rgb[indx+v2][c]+rgb[indx-v2][c]); - grblpfh[indx] = glpfh + 0.25*(2*rgb[indx][c]+rgb[indx+2][c]+rgb[indx-2][c]); - } - - for (c=0;c<3;c++) {areawt[0][c]=areawt[1][c]=0;} - - // along line segments, find the point along each segment that minimizes the color variance - // averaged over the tile; evaluate for up/down and left/right away from R/B grid point - for (rr=rrmin+8; rr < rrmax-8; rr++) - for (cc=ccmin+8+(FC(rr,2)&1), indx=rr*TS+cc, c = FC(rr,cc); cc < ccmax-8; cc+=2, indx+=2) { - - if (rgb[indx][c]>0.8*clip_pt || Gtmp[indx]>0.8*clip_pt) continue; - - //in linear interpolation, color differences are a quadratic function of interpolation position; - //solve for the interpolation position that minimizes color difference variance over the tile + //in linear interpolation, colour differences are a quadratic function of interpolation position; + //solve for the interpolation position that minimizes colour difference variance over the tile //vertical - gdiff=0.3125*(rgb[indx+TS][1]-rgb[indx-TS][1])+0.09375*(rgb[indx+TS+1][1]-rgb[indx-TS+1][1]+rgb[indx+TS-1][1]-rgb[indx-TS-1][1]); - deltgrb=(rgb[indx][c]-rgb[indx][1])-0.5*((rgb[indx-v4][c]-rgb[indx-v4][1])+(rgb[indx+v4][c]-rgb[indx+v4][1])); + float gdiff = 0.3125f * (rgb[1][indx + ts] - rgb[1][indx - ts]) + 0.09375f * (rgb[1][indx + ts + 1] - rgb[1][indx - ts + 1] + rgb[1][indx + ts - 1] - rgb[1][indx - ts - 1]); + float deltgrb = (rgb[c][indx] - rgb[1][indx]); - gradwt=fabs(0.25*rbhpfv[indx]+0.125*(rbhpfv[indx+2]+rbhpfv[indx-2]) );// *(grblpfv[indx-v2]+grblpfv[indx+v2])/(eps+0.1*grblpfv[indx-v2]+rblpfv[indx-v2]+0.1*grblpfv[indx+v2]+rblpfv[indx+v2]); - if (gradwt>eps) { - coeff[0][0][c] += gradwt*deltgrb*deltgrb; - coeff[0][1][c] += gradwt*gdiff*deltgrb; - coeff[0][2][c] += gradwt*gdiff*gdiff; - areawt[0][c]++; - } + float gradwt = fabsf(0.25f * rbhpfv[indx >> 1] + 0.125f * (rbhpfv[(indx >> 1) + 1] + rbhpfv[(indx >> 1) - 1]) ) * (grblpfv[(indx >> 1) - v1] + grblpfv[(indx >> 1) + v1]) / (eps + 0.1f * (grblpfv[(indx >> 1) - v1] + grblpfv[(indx >> 1) + v1]) + rblpfv[(indx >> 1) - v1] + rblpfv[(indx >> 1) + v1]); + + coeff[0][0][c>>1] += gradwt * deltgrb * deltgrb; + coeff[0][1][c>>1] += gradwt * gdiff * deltgrb; + coeff[0][2][c>>1] += gradwt * gdiff * gdiff; //horizontal - gdiff=0.3125*(rgb[indx+1][1]-rgb[indx-1][1])+0.09375*(rgb[indx+1+TS][1]-rgb[indx-1+TS][1]+rgb[indx+1-TS][1]-rgb[indx-1-TS][1]); - deltgrb=(rgb[indx][c]-rgb[indx][1])-0.5*((rgb[indx-4][c]-rgb[indx-4][1])+(rgb[indx+4][c]-rgb[indx+4][1])); + gdiff = 0.3125f * (rgb[1][indx + 1] - rgb[1][indx - 1]) + 0.09375f * (rgb[1][indx + 1 + ts] - rgb[1][indx - 1 + ts] + rgb[1][indx + 1 - ts] - rgb[1][indx - 1 - ts]); - gradwt=fabs(0.25*rbhpfh[indx]+0.125*(rbhpfh[indx+v2]+rbhpfh[indx-v2]) );// *(grblpfh[indx-2]+grblpfh[indx+2])/(eps+0.1*grblpfh[indx-2]+rblpfh[indx-2]+0.1*grblpfh[indx+2]+rblpfh[indx+2]); - if (gradwt>eps) { - coeff[1][0][c] += gradwt*deltgrb*deltgrb; - coeff[1][1][c] += gradwt*gdiff*deltgrb; - coeff[1][2][c] += gradwt*gdiff*gdiff; - areawt[1][c]++; - } + gradwt = fabsf(0.25f * rbhpfh[indx >> 1] + 0.125f * (rbhpfh[(indx >> 1) + v1] + rbhpfh[(indx >> 1) - v1]) ) * (grblpfh[(indx >> 1) - 1] + grblpfh[(indx >> 1) + 1]) / (eps + 0.1f * (grblpfh[(indx >> 1) - 1] + grblpfh[(indx >> 1) + 1]) + rblpfh[(indx >> 1) - 1] + rblpfh[(indx >> 1) + 1]); + + coeff[1][0][c>>1] += gradwt * deltgrb * deltgrb; + coeff[1][1][c>>1] += gradwt * gdiff * deltgrb; + coeff[1][2][c>>1] += gradwt * gdiff * gdiff; // In Mathematica, // f[x_]=Expand[Total[Flatten[ // ((1-x) RotateLeft[Gint,shift1]+x RotateLeft[Gint,shift2]-cfapad)^2[[dv;;-1;;2,dh;;-1;;2]]]]]; // extremum = -.5Coefficient[f[x],x]/Coefficient[f[x],x^2] - }*/ - for (c = 0; c < 3; c += 2) { - for (j = 0; j < 2; j++) { // vert/hor - //printf("hblock %d vblock %d j %d c %d areawt %d \n",hblock,vblock,j,c,areawt[j][c]); - //printf("hblock %d vblock %d j %d c %d areawt %d ",hblock,vblock,j,c,areawt[j][c]); + } + } - if (areawt[j][c] > 0 && coeff[j][2][c] > eps2) { - CAshift[j][c] = coeff[j][1][c] / coeff[j][2][c]; - blockwt[vblock * hblsz + hblock] = areawt[j][c] * coeff[j][2][c] / (eps + coeff[j][0][c]) ; + for (int c = 0; c < 2; c++) { + for (int dir = 0; dir < 2; dir++) { // vert/hor + + // CAshift[dir][c] are the locations + // that minimize colour difference variances; + // This is the approximate _optical_ location of the R/B pixels + if (coeff[dir][2][c] > eps2) { + CAshift[dir][c] = coeff[dir][1][c] / coeff[dir][2][c]; + blockwt[vblock * hblsz + hblock] = coeff[dir][2][c] / (eps + coeff[dir][0][c]) ; } else { - CAshift[j][c] = 17.0; + CAshift[dir][c] = 17.0; blockwt[vblock * hblsz + hblock] = 0; } - //if (c==0 && j==0) printf("vblock= %d hblock= %d denom= %f areawt= %d \n",vblock,hblock,coeff[j][2][c],areawt[j][c]); + //data structure = CAshift[vert/hor][colour] + //dir : 0=vert, 1=hor - //printf("%f \n",CAshift[j][c]); - - //data structure = CAshift[vert/hor][color] - //j=0=vert, 1=hor - - //offset gives NW corner of square containing the min; j=0=vert, 1=hor - - if (fabsf(CAshift[j][c]) < 2.0f) { - blockavethr[j][c] += CAshift[j][c]; - blocksqavethr[j][c] += SQR(CAshift[j][c]); - blockdenomthr[j][c] += 1; + //offset gives NW corner of square containing the min; dir : 0=vert, 1=hor + if (fabsf(CAshift[dir][c]) < 2.0f) { + blockavethr[dir][c] += CAshift[dir][c]; + blocksqavethr[dir][c] += SQR(CAshift[dir][c]); + blockdenomthr[dir][c] += 1; } + //evaluate the shifts to the location that minimizes CA within the tile + blockshifts[vblock * hblsz + hblock][c][dir] = CAshift[dir][c]; //vert/hor CA shift for R/B + }//vert/hor - }//color - - /* CAshift[j][c] are the locations - that minimize color difference variances; - This is the approximate _optical_ location of the R/B pixels */ - - for (c = 0; c < 3; c += 2) { - //evaluate the shifts to the location that minimizes CA within the tile - blockshifts[(vblock)*hblsz + hblock][c][0] = (CAshift[0][c]); //vert CA shift for R/B - blockshifts[(vblock)*hblsz + hblock][c][1] = (CAshift[1][c]); //hor CA shift for R/B - //data structure: blockshifts[blocknum][R/B][v/h] - //if (c==0) printf("vblock= %d hblock= %d blockshiftsmedian= %f \n",vblock,hblock,blockshifts[(vblock)*hblsz+hblock][c][0]); - } + }//colour if(plistener) { progresscounter++; if(progresscounter % 8 == 0) - #pragma omp critical + #pragma omp critical (cadetectpass1) { - progress += (double)(8.0 * (TS - border2) * (TS - border2)) / (2 * height * width); + progress += (double)(8.0 * (ts - border2) * (ts - border2)) / (2 * height * width); if (progress > 1.0) { progress = 1.0; @@ -640,23 +560,23 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) } //end of diagnostic pass - #pragma omp critical + #pragma omp critical (cadetectpass2) { - for (j = 0; j < 2; j++) - for (c = 0; c < 3; c += 2) { - blockdenom[j][c] += blockdenomthr[j][c]; - blocksqave[j][c] += blocksqavethr[j][c]; - blockave[j][c] += blockavethr[j][c]; + for (int dir = 0; dir < 2; dir++) + for (int c = 0; c < 2; c++) { + blockdenom[dir][c] += blockdenomthr[dir][c]; + blocksqave[dir][c] += blocksqavethr[dir][c]; + blockave[dir][c] += blockavethr[dir][c]; } } #pragma omp barrier #pragma omp single { - for (j = 0; j < 2; j++) - for (c = 0; c < 3; c += 2) { - if (blockdenom[j][c]) { - blockvar[j][c] = blocksqave[j][c] / blockdenom[j][c] - SQR(blockave[j][c] / blockdenom[j][c]); + for (int dir = 0; dir < 2; dir++) + for (int c = 0; c < 2; c++) { + if (blockdenom[dir][c]) { + blockvar[dir][c] = blocksqave[dir][c] / blockdenom[dir][c] - SQR(blockave[dir][c] / blockdenom[dir][c]); } else { processpasstwo = false; printf ("blockdenom vanishes \n"); @@ -664,26 +584,23 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) } } - //printf ("tile variances %f %f %f %f \n",blockvar[0][0],blockvar[1][0],blockvar[0][2],blockvar[1][2] ); - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //now prepare for CA correction pass //first, fill border blocks of blockshift array if(processpasstwo) { - for (vblock = 1; vblock < vblsz - 1; vblock++) { //left and right sides - for (c = 0; c < 3; c += 2) { - for (i = 0; i < 2; i++) { + for (int vblock = 1; vblock < vblsz - 1; vblock++) { //left and right sides + for (int c = 0; c < 2; c++) { + for (int i = 0; i < 2; i++) { blockshifts[vblock * hblsz][c][i] = blockshifts[(vblock) * hblsz + 2][c][i]; blockshifts[vblock * hblsz + hblsz - 1][c][i] = blockshifts[(vblock) * hblsz + hblsz - 3][c][i]; } } } - for (hblock = 0; hblock < hblsz; hblock++) { //top and bottom sides - for (c = 0; c < 3; c += 2) { - for (i = 0; i < 2; i++) { + for (int hblock = 0; hblock < hblsz; hblock++) { //top and bottom sides + for (int c = 0; c < 2; c++) { + for (int i = 0; i < 2; i++) { blockshifts[hblock][c][i] = blockshifts[2 * hblsz + hblock][c][i]; blockshifts[(vblsz - 1)*hblsz + hblock][c][i] = blockshifts[(vblsz - 3) * hblsz + hblock][c][i]; } @@ -693,25 +610,26 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) //end of filling border pixels of blockshift array //initialize fit arrays - double polymat[3][2][256], shiftmat[3][2][16]; + double polymat[2][2][256], shiftmat[2][2][16]; - for (i = 0; i < 256; i++) { - polymat[0][0][i] = polymat[0][1][i] = polymat[2][0][i] = polymat[2][1][i] = 0; + for (int i = 0; i < 256; i++) { + polymat[0][0][i] = polymat[0][1][i] = polymat[1][0][i] = polymat[1][1][i] = 0; } - for (i = 0; i < 16; i++) { - shiftmat[0][0][i] = shiftmat[0][1][i] = shiftmat[2][0][i] = shiftmat[2][1][i] = 0; + for (int i = 0; i < 16; i++) { + shiftmat[0][0][i] = shiftmat[0][1][i] = shiftmat[1][0][i] = shiftmat[1][1][i] = 0; } - int numblox[3] = {0, 0, 0}; + int numblox[2] = {0, 0}; - float bstemp[2]; - - for (vblock = 1; vblock < vblsz - 1; vblock++) - for (hblock = 1; hblock < hblsz - 1; hblock++) { + for (int vblock = 1; vblock < vblsz - 1; vblock++) + for (int hblock = 1; hblock < hblsz - 1; hblock++) { // block 3x3 median of blockshifts for robustness - for (c = 0; c < 3; c += 2) { - for (dir = 0; dir < 2; dir++) { + for (int c = 0; c < 2; c ++) { + float bstemp[2]; + for (int dir = 0; dir < 2; dir++) { + //temporary storage for median filter + float p[9]; p[0] = blockshifts[(vblock - 1) * hblsz + hblock - 1][c][dir]; p[1] = blockshifts[(vblock - 1) * hblsz + hblock][c][dir]; p[2] = blockshifts[(vblock - 1) * hblsz + hblock + 1][c][dir]; @@ -721,57 +639,59 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) p[6] = blockshifts[(vblock + 1) * hblsz + hblock - 1][c][dir]; p[7] = blockshifts[(vblock + 1) * hblsz + hblock][c][dir]; p[8] = blockshifts[(vblock + 1) * hblsz + hblock + 1][c][dir]; - PIX_SORT(p[1], p[2]); - PIX_SORT(p[4], p[5]); - PIX_SORT(p[7], p[8]); - PIX_SORT(p[0], p[1]); - PIX_SORT(p[3], p[4]); - PIX_SORT(p[6], p[7]); - PIX_SORT(p[1], p[2]); - PIX_SORT(p[4], p[5]); - PIX_SORT(p[7], p[8]); - PIX_SORT(p[0], p[3]); - PIX_SORT(p[5], p[8]); - PIX_SORT(p[4], p[7]); - PIX_SORT(p[3], p[6]); - PIX_SORT(p[1], p[4]); - PIX_SORT(p[2], p[5]); - PIX_SORT(p[4], p[7]); - PIX_SORT(p[4], p[2]); - PIX_SORT(p[6], p[4]); - PIX_SORT(p[4], p[2]); + pixSort(p[1], p[2]); + pixSort(p[4], p[5]); + pixSort(p[7], p[8]); + pixSort(p[0], p[1]); + pixSort(p[3], p[4]); + pixSort(p[6], p[7]); + pixSort(p[1], p[2]); + pixSort(p[4], p[5]); + pixSort(p[7], p[8]); + pixSort(p[0], p[3]); + pixSort(p[5], p[8]); + pixSort(p[4], p[7]); + pixSort(p[3], p[6]); + pixSort(p[1], p[4]); + pixSort(p[2], p[5]); + pixSort(p[4], p[7]); + pixSort(p[4], p[2]); + pixSort(p[6], p[4]); + pixSort(p[4], p[2]); bstemp[dir] = p[4]; - //if (c==0 && dir==0) printf("vblock= %d hblock= %d blockshiftsmedian= %f \n",vblock,hblock,p[4]); } - //if (verbose) fprintf (stderr,_("tile vshift hshift (%d %d %4f %4f)...\n"),vblock, hblock, blockshifts[(vblock)*hblsz+hblock][c][0], blockshifts[(vblock)*hblsz+hblock][c][1]); - - //now prepare coefficient matrix; use only data points within two std devs of zero - if (SQR(bstemp[0]) > 4.0 * blockvar[0][c] || SQR(bstemp[1]) > 4.0 * blockvar[1][c]) { + //now prepare coefficient matrix; use only data points within caautostrength/2 std devs of zero + if (SQR(bstemp[0]) > caautostrength * blockvar[0][c] || SQR(bstemp[1]) > caautostrength * blockvar[1][c]) { continue; } numblox[c]++; - for (dir = 0; dir < 2; dir++) { - for (i = 0; i < polyord; i++) { - for (j = 0; j < polyord; j++) { - for (m = 0; m < polyord; m++) - for (n = 0; n < polyord; n++) { - polymat[c][dir][numpar * (polyord * i + j) + (polyord * m + n)] += (float)pow((double)vblock, i + m) * pow((double)hblock, j + n) * blockwt[vblock * hblsz + hblock]; + for (int dir = 0; dir < 2; dir++) { + double powVblockInit = 1.0; + for (int i = 0; i < polyord; i++) { + double powHblockInit = 1.0; + for (int j = 0; j < polyord; j++) { + double powVblock = powVblockInit; + for (int m = 0; m < polyord; m++) { + double powHblock = powHblockInit; + for (int n = 0; n < polyord; n++) { + polymat[c][dir][numpar * (polyord * i + j) + (polyord * m + n)] += powVblock * powHblock * blockwt[vblock * hblsz + hblock]; + powHblock *= hblock; } - - shiftmat[c][dir][(polyord * i + j)] += (float)pow((double)vblock, i) * pow((double)hblock, j) * bstemp[dir] * blockwt[vblock * hblsz + hblock]; + powVblock *= vblock; + } + shiftmat[c][dir][(polyord * i + j)] += powVblockInit * powHblockInit * bstemp[dir] * blockwt[vblock * hblsz + hblock]; + powHblockInit *= hblock; } - - //if (c==0 && dir==0) {printf("i= %d j= %d shiftmat= %f \n",i,j,shiftmat[c][dir][(polyord*i+j)]);} + powVblockInit *= vblock; }//monomials }//dir - }//c }//blocks - numblox[1] = min(numblox[0], numblox[2]); + numblox[1] = min(numblox[0], numblox[1]); //if too few data points, restrict the order of the fit to linear if (numblox[1] < 32) { @@ -788,12 +708,10 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) if(processpasstwo) //fit parameters to blockshifts - for (c = 0; c < 3; c += 2) - for (dir = 0; dir < 2; dir++) { - res = LinEqSolve(numpar, polymat[c][dir], shiftmat[c][dir], fitparams[c][dir]); - - if (res) { - printf("CA correction pass failed -- can't solve linear equations for color %d direction %d...\n", c, dir); + for (int c = 0; c < 2; c++) + for (int dir = 0; dir < 2; dir++) { + if (!LinEqSolve(numpar, polymat[c][dir], shiftmat[c][dir], fitparams[c][dir])) { + printf("CA correction pass failed -- can't solve linear equations for colour %d direction %d...\n", c, dir); processpasstwo = false; } } @@ -810,53 +728,32 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) if(processpasstwo) { #pragma omp for schedule(dynamic) collapse(2) nowait - for (top = -border; top < height; top += TS - border2) - for (left = -border; left < width; left += TS - border2) { - vblock = ((top + border) / (TS - border2)) + 1; - hblock = ((left + border) / (TS - border2)) + 1; - int bottom = min(top + TS, height + border); - int right = min(left + TS, width + border); - int rr1 = bottom - top; - int cc1 = right - left; + for (int top = -border; top < height; top += ts - border2) + for (int left = -border; left < width; left += ts - border2) { + float lblockshifts[2][2]; + const int vblock = ((top + border) / (ts - border2)) + 1; + const int hblock = ((left + border) / (ts - border2)) + 1; + const int bottom = min(top + ts, height + border); + const int right = min(left + ts, width + border); + const int rr1 = bottom - top; + const int cc1 = right - left; - //t1_init = clock(); - if (top < 0) { - rrmin = border; - } else { - rrmin = 0; - } - - if (left < 0) { - ccmin = border; - } else { - ccmin = 0; - } - - if (bottom > height) { - rrmax = height - top; - } else { - rrmax = rr1; - } - - if (right > width) { - ccmax = width - left; - } else { - ccmax = cc1; - } + const int rrmin = top < 0 ? border : 0; + const int rrmax = bottom > height ? height - top : rr1; + const int ccmin = left < 0 ? border : 0; + const int ccmax = right > width ? width - left : cc1; // rgb from input CFA data // rgb values should be floating point number between 0 and 1 // after white balance multipliers are applied - for (rr = rrmin; rr < rrmax; rr++) - for (row = rr + top, cc = ccmin; cc < ccmax; cc++) { - col = cc + left; - c = FC(rr, cc); - indx = row * width + col; - indx1 = rr * TS + cc; - //rgb[indx1][c] = image[indx][c]/65535.0f; + for (int rr = rrmin; rr < rrmax; rr++) + for (int row = rr + top, cc = ccmin; cc < ccmax; cc++) { + int col = cc + left; + int c = FC(rr, cc); + int indx = row * width + col; + int indx1 = rr * ts + cc; rgb[c][indx1] = (rawData[row][col]) / 65535.0f; - //rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation if ((c & 1) == 0) { rgb[1][indx1] = Gtmp[indx]; @@ -866,87 +763,75 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //fill borders if (rrmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = ccmin; cc < ccmax; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + cc] = rgb[c][(border2 - rr) * TS + cc]; - rgb[1][rr * TS + cc] = rgb[1][(border2 - rr) * TS + cc]; + for (int rr = 0; rr < border; rr++) + for (int cc = ccmin; cc < ccmax; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + cc] = rgb[c][(border2 - rr) * ts + cc]; + rgb[1][rr * ts + cc] = rgb[1][(border2 - rr) * ts + cc]; } } if (rrmax < rr1) { - for (rr = 0; rr < border; rr++) - for (cc = ccmin; cc < ccmax; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + cc] = (rawData[(height - rr - 2)][left + cc]) / 65535.0f; - //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+left+cc][c])/65535.0f;//for dcraw implementation - - rgb[1][(rrmax + rr)*TS + cc] = Gtmp[(height - rr - 2) * width + left + cc]; + for (int rr = 0; rr < border; rr++) + for (int cc = ccmin; cc < ccmax; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + cc] = (rawData[(height - rr - 2)][left + cc]) / 65535.0f; + rgb[1][(rrmax + rr)*ts + cc] = Gtmp[(height - rr - 2) * width + left + cc]; } } if (ccmin > 0) { - for (rr = rrmin; rr < rrmax; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + cc] = rgb[c][rr * TS + border2 - cc]; - rgb[1][rr * TS + cc] = rgb[1][rr * TS + border2 - cc]; + for (int rr = rrmin; rr < rrmax; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + cc] = rgb[c][rr * ts + border2 - cc]; + rgb[1][rr * ts + cc] = rgb[1][rr * ts + border2 - cc]; } } if (ccmax < cc1) { - for (rr = rrmin; rr < rrmax; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][rr * TS + ccmax + cc] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.0f; - //rgb[rr*TS+ccmax+cc][c] = (image[(top+rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation - - rgb[1][rr * TS + ccmax + cc] = Gtmp[(top + rr) * width + (width - cc - 2)]; + for (int rr = rrmin; rr < rrmax; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][rr * ts + ccmax + cc] = (rawData[(top + rr)][(width - cc - 2)]) / 65535.0f; + rgb[1][rr * ts + ccmax + cc] = Gtmp[(top + rr) * width + (width - cc - 2)]; } } //also, fill the image corners if (rrmin > 0 && ccmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rr)*TS + cc] = (rawData[border2 - rr][border2 - cc]) / 65535.0f; - //rgb[(rr)*TS+cc][c] = (rgb[(border2-rr)*TS+(border2-cc)][c]);//for dcraw implementation - - rgb[1][(rr)*TS + cc] = Gtmp[(border2 - rr) * width + border2 - cc]; + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rr)*ts + cc] = (rawData[border2 - rr][border2 - cc]) / 65535.0f; + rgb[1][(rr)*ts + cc] = Gtmp[(border2 - rr) * width + border2 - cc]; } } if (rrmax < rr1 && ccmax < cc1) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + ccmax + cc] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.0f; - //rgb[(rrmax+rr)*TS+ccmax+cc][c] = (image[(height-rr-2)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation - - rgb[1][(rrmax + rr)*TS + ccmax + cc] = Gtmp[(height - rr - 2) * width + (width - cc - 2)]; + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + ccmax + cc] = (rawData[(height - rr - 2)][(width - cc - 2)]) / 65535.0f; + rgb[1][(rrmax + rr)*ts + ccmax + cc] = Gtmp[(height - rr - 2) * width + (width - cc - 2)]; } } if (rrmin > 0 && ccmax < cc1) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rr)*TS + ccmax + cc] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.0f; - //rgb[(rr)*TS+ccmax+cc][c] = (image[(border2-rr)*width+(width-cc-2)][c])/65535.0f;//for dcraw implementation - - rgb[1][(rr)*TS + ccmax + cc] = Gtmp[(border2 - rr) * width + (width - cc - 2)]; + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rr)*ts + ccmax + cc] = (rawData[(border2 - rr)][(width - cc - 2)]) / 65535.0f; + rgb[1][(rr)*ts + ccmax + cc] = Gtmp[(border2 - rr) * width + (width - cc - 2)]; } } if (rrmax < rr1 && ccmin > 0) { - for (rr = 0; rr < border; rr++) - for (cc = 0; cc < border; cc++) { - c = FC(rr, cc); - rgb[c][(rrmax + rr)*TS + cc] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.0f; - //rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(border2-cc)][c])/65535.0f;//for dcraw implementation - - rgb[1][(rrmax + rr)*TS + cc] = Gtmp[(height - rr - 2) * width + (border2 - cc)]; + for (int rr = 0; rr < border; rr++) + for (int cc = 0; cc < border; cc++) { + int c = FC(rr, cc); + rgb[c][(rrmax + rr)*ts + cc] = (rawData[(height - rr - 2)][(border2 - cc)]) / 65535.0f; + rgb[1][(rrmax + rr)*ts + cc] = Gtmp[(height - rr - 2) * width + (border2 - cc)]; } } @@ -955,17 +840,17 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) if (!autoCA) { //manual CA correction; use red/blue slider values to set CA shift parameters - for (rr = 3; rr < rr1 - 3; rr++) - for (row = rr + top, cc = 3, indx = rr * TS + cc; cc < cc1 - 3; cc++, indx++) { - col = cc + left; - c = FC(rr, cc); + for (int rr = 3; rr < rr1 - 3; rr++) + for (int row = rr + top, cc = 3, indx = rr * ts + cc; cc < cc1 - 3; cc++, indx++) { + int col = cc + left; + int c = FC(rr, cc); if (c != 1) { //compute directional weights using image gradients - wtu = 1.0 / SQR(eps + fabsf(rgb[1][(rr + 1) * TS + cc] - rgb[1][(rr - 1) * TS + cc]) + fabsf(rgb[c][(rr) * TS + cc] - rgb[c][(rr - 2) * TS + cc]) + fabsf(rgb[1][(rr - 1) * TS + cc] - rgb[1][(rr - 3) * TS + cc])); - wtd = 1.0 / SQR(eps + fabsf(rgb[1][(rr - 1) * TS + cc] - rgb[1][(rr + 1) * TS + cc]) + fabsf(rgb[c][(rr) * TS + cc] - rgb[c][(rr + 2) * TS + cc]) + fabsf(rgb[1][(rr + 1) * TS + cc] - rgb[1][(rr + 3) * TS + cc])); - wtl = 1.0 / SQR(eps + fabsf(rgb[1][(rr) * TS + cc + 1] - rgb[1][(rr) * TS + cc - 1]) + fabsf(rgb[c][(rr) * TS + cc] - rgb[c][(rr) * TS + cc - 2]) + fabsf(rgb[1][(rr) * TS + cc - 1] - rgb[1][(rr) * TS + cc - 3])); - wtr = 1.0 / SQR(eps + fabsf(rgb[1][(rr) * TS + cc - 1] - rgb[1][(rr) * TS + cc + 1]) + fabsf(rgb[c][(rr) * TS + cc] - rgb[c][(rr) * TS + cc + 2]) + fabsf(rgb[1][(rr) * TS + cc + 1] - rgb[1][(rr) * TS + cc + 3])); + float wtu = 1.0 / SQR(eps + fabsf(rgb[1][(rr + 1) * ts + cc] - rgb[1][(rr - 1) * ts + cc]) + fabsf(rgb[c][(rr) * ts + cc] - rgb[c][(rr - 2) * ts + cc]) + fabsf(rgb[1][(rr - 1) * ts + cc] - rgb[1][(rr - 3) * ts + cc])); + float wtd = 1.0 / SQR(eps + fabsf(rgb[1][(rr - 1) * ts + cc] - rgb[1][(rr + 1) * ts + cc]) + fabsf(rgb[c][(rr) * ts + cc] - rgb[c][(rr + 2) * ts + cc]) + fabsf(rgb[1][(rr + 1) * ts + cc] - rgb[1][(rr + 3) * ts + cc])); + float wtl = 1.0 / SQR(eps + fabsf(rgb[1][(rr) * ts + cc + 1] - rgb[1][(rr) * ts + cc - 1]) + fabsf(rgb[c][(rr) * ts + cc] - rgb[c][(rr) * ts + cc - 2]) + fabsf(rgb[1][(rr) * ts + cc - 1] - rgb[1][(rr) * ts + cc - 3])); + float wtr = 1.0 / SQR(eps + fabsf(rgb[1][(rr) * ts + cc - 1] - rgb[1][(rr) * ts + cc + 1]) + fabsf(rgb[c][(rr) * ts + cc] - rgb[c][(rr) * ts + cc + 2]) + fabsf(rgb[1][(rr) * ts + cc + 1] - rgb[1][(rr) * ts + cc + 3])); //store in rgb array the interpolated G value at R/B grid points using directional weighted average rgb[1][indx] = (wtu * rgb[1][indx - v1] + wtd * rgb[1][indx + v1] + wtl * rgb[1][indx - 1] + wtr * rgb[1][indx + 1]) / (wtu + wtd + wtl + wtr); @@ -978,89 +863,105 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) float hfrac = -((float)(hblock - 0.5) / (hblsz - 2) - 0.5); float vfrac = -((float)(vblock - 0.5) / (vblsz - 2) - 0.5) * height / width; - blockshifts[(vblock)*hblsz + hblock][0][0] = 2 * vfrac * cared; - blockshifts[(vblock)*hblsz + hblock][0][1] = 2 * hfrac * cared; - blockshifts[(vblock)*hblsz + hblock][2][0] = 2 * vfrac * cablue; - blockshifts[(vblock)*hblsz + hblock][2][1] = 2 * hfrac * cablue; + lblockshifts[0][0] = 2 * vfrac * cared; + lblockshifts[0][1] = 2 * hfrac * cared; + lblockshifts[1][0] = 2 * vfrac * cablue; + lblockshifts[1][1] = 2 * hfrac * cablue; } else { //CA auto correction; use CA diagnostic pass to set shift parameters - blockshifts[(vblock)*hblsz + hblock][0][0] = blockshifts[(vblock) * hblsz + hblock][0][1] = 0; - blockshifts[(vblock)*hblsz + hblock][2][0] = blockshifts[(vblock) * hblsz + hblock][2][1] = 0; - - for (i = 0; i < polyord; i++) - for (j = 0; j < polyord; j++) { + lblockshifts[0][0] = lblockshifts[0][1] = 0; + lblockshifts[1][0] = lblockshifts[1][1] = 0; + double powVblock = 1.0; + for (int i = 0; i < polyord; i++) { + double powHblock = powVblock; + for (int j = 0; j < polyord; j++) { //printf("i= %d j= %d polycoeff= %f \n",i,j,fitparams[0][0][polyord*i+j]); - blockshifts[(vblock)*hblsz + hblock][0][0] += (float)pow((float)vblock, i) * pow((float)hblock, j) * fitparams[0][0][polyord * i + j]; - blockshifts[(vblock)*hblsz + hblock][0][1] += (float)pow((float)vblock, i) * pow((float)hblock, j) * fitparams[0][1][polyord * i + j]; - blockshifts[(vblock)*hblsz + hblock][2][0] += (float)pow((float)vblock, i) * pow((float)hblock, j) * fitparams[2][0][polyord * i + j]; - blockshifts[(vblock)*hblsz + hblock][2][1] += (float)pow((float)vblock, i) * pow((float)hblock, j) * fitparams[2][1][polyord * i + j]; + lblockshifts[0][0] += powHblock * fitparams[0][0][polyord * i + j]; + lblockshifts[0][1] += powHblock * fitparams[0][1][polyord * i + j]; + lblockshifts[1][0] += powHblock * fitparams[1][0][polyord * i + j]; + lblockshifts[1][1] += powHblock * fitparams[1][1][polyord * i + j]; + powHblock *= hblock; } - - blockshifts[(vblock)*hblsz + hblock][0][0] = LIM(blockshifts[(vblock) * hblsz + hblock][0][0], -bslim, bslim); - blockshifts[(vblock)*hblsz + hblock][0][1] = LIM(blockshifts[(vblock) * hblsz + hblock][0][1], -bslim, bslim); - blockshifts[(vblock)*hblsz + hblock][2][0] = LIM(blockshifts[(vblock) * hblsz + hblock][2][0], -bslim, bslim); - blockshifts[(vblock)*hblsz + hblock][2][1] = LIM(blockshifts[(vblock) * hblsz + hblock][2][1], -bslim, bslim); + powVblock *= vblock; + } + constexpr float bslim = 3.99; //max allowed CA shift + lblockshifts[0][0] = LIM(lblockshifts[0][0], -bslim, bslim); + lblockshifts[0][1] = LIM(lblockshifts[0][1], -bslim, bslim); + lblockshifts[1][0] = LIM(lblockshifts[1][0], -bslim, bslim); + lblockshifts[1][1] = LIM(lblockshifts[1][1], -bslim, bslim); }//end of setting CA shift parameters - //printf("vblock= %d hblock= %d vshift= %f hshift= %f \n",vblock,hblock,blockshifts[(vblock)*hblsz+hblock][0][0],blockshifts[(vblock)*hblsz+hblock][0][1]); - for (c = 0; c < 3; c += 2) { + for (int c = 0; c < 3; c += 2) { //some parameters for the bilinear interpolation - shiftvfloor[c] = floor((float)blockshifts[(vblock) * hblsz + hblock][c][0]); - shiftvceil[c] = ceil((float)blockshifts[(vblock) * hblsz + hblock][c][0]); - shiftvfrac[c] = blockshifts[(vblock) * hblsz + hblock][c][0] - shiftvfloor[c]; + shiftvfloor[c] = floor((float)lblockshifts[c>>1][0]); + shiftvceil[c] = ceil((float)lblockshifts[c>>1][0]); + shiftvfrac[c] = lblockshifts[c>>1][0] - shiftvfloor[c]; - shifthfloor[c] = floor((float)blockshifts[(vblock) * hblsz + hblock][c][1]); - shifthceil[c] = ceil((float)blockshifts[(vblock) * hblsz + hblock][c][1]); - shifthfrac[c] = blockshifts[(vblock) * hblsz + hblock][c][1] - shifthfloor[c]; + shifthfloor[c] = floor((float)lblockshifts[c>>1][1]); + shifthceil[c] = ceil((float)lblockshifts[c>>1][1]); + shifthfrac[c] = lblockshifts[c>>1][1] - shifthfloor[c]; - - if (blockshifts[(vblock)*hblsz + hblock][c][0] > 0) { - GRBdir[0][c] = 1; - } else { - GRBdir[0][c] = -1; - } - - if (blockshifts[(vblock)*hblsz + hblock][c][1] > 0) { - GRBdir[1][c] = 1; - } else { - GRBdir[1][c] = -1; - } + GRBdir[0][c] = lblockshifts[c>>1][0] > 0 ? 2 : -2; + GRBdir[1][c] = lblockshifts[c>>1][1] > 0 ? 2 : -2; } - for (rr = 4; rr < rr1 - 4; rr++) - for (cc = 4 + (FC(rr, 2) & 1), c = FC(rr, cc); cc < cc1 - 4; cc += 2) { - //perform CA correction using color ratios or color differences + for (int rr = 4; rr < rr1 - 4; rr++) { + int cc = 4 + (FC(rr, 2) & 1); + int c = FC(rr, cc); +#ifdef __SSE2__ + vfloat shifthfracv = F2V(shifthfrac[c]); + vfloat shiftvfracv = F2V(shiftvfrac[c]); + for (; cc < cc1 - 10; cc += 8) { + //perform CA correction using colour ratios or colour differences + vfloat Ginthfloorv = vintpf(shifthfracv, LC2VFU(rgb[1][(rr + shiftvfloor[c]) * ts + cc + shifthceil[c]]), LC2VFU(rgb[1][(rr + shiftvfloor[c]) * ts + cc + shifthfloor[c]])); + vfloat Ginthceilv = vintpf(shifthfracv, LC2VFU(rgb[1][(rr + shiftvceil[c]) * ts + cc + shifthceil[c]]), LC2VFU(rgb[1][(rr + shiftvceil[c]) * ts + cc + shifthfloor[c]])); + //Gint is bilinear interpolation of G at CA shift point + vfloat Gintv = vintpf(shiftvfracv, Ginthceilv, Ginthfloorv); - Ginthfloor = (1 - shifthfrac[c]) * rgb[1][(rr + shiftvfloor[c]) * TS + cc + shifthfloor[c]] + (shifthfrac[c]) * rgb[1][(rr + shiftvfloor[c]) * TS + cc + shifthceil[c]]; - Ginthceil = (1 - shifthfrac[c]) * rgb[1][(rr + shiftvceil[c]) * TS + cc + shifthfloor[c]] + (shifthfrac[c]) * rgb[1][(rr + shiftvceil[c]) * TS + cc + shifthceil[c]]; - //Gint is blinear interpolation of G at CA shift point - Gint = (1 - shiftvfrac[c]) * Ginthfloor + (shiftvfrac[c]) * Ginthceil; - - //determine R/B at grid points using color differences at shift point plus interpolated G value at grid point + //determine R/B at grid points using colour differences at shift point plus interpolated G value at grid point //but first we need to interpolate G-R/G-B to grid points... - grbdiff[((rr)*TS + cc) >> 1] = Gint - rgb[c][(rr) * TS + cc]; - gshift[((rr)*TS + cc) >> 1] = Gint; + STVFU(grbdiff[((rr)*ts + cc) >> 1], Gintv - LC2VFU(rgb[c][(rr) * ts + cc])); + STVFU(gshift[((rr)*ts + cc) >> 1], Gintv); } - for (rr = 8; rr < rr1 - 8; rr++) - for (cc = 8 + (FC(rr, 2) & 1), c = FC(rr, cc), indx = rr * TS + cc; cc < cc1 - 8; cc += 2, indx += 2) { +#endif + for (; cc < cc1 - 4; cc += 2) { + //perform CA correction using colour ratios or colour differences + float Ginthfloor = intp(shifthfrac[c], rgb[1][(rr + shiftvfloor[c]) * ts + cc + shifthceil[c]], rgb[1][(rr + shiftvfloor[c]) * ts + cc + shifthfloor[c]]); + float Ginthceil = intp(shifthfrac[c], rgb[1][(rr + shiftvceil[c]) * ts + cc + shifthceil[c]], rgb[1][(rr + shiftvceil[c]) * ts + cc + shifthfloor[c]]); + //Gint is bilinear interpolation of G at CA shift point + float Gint = intp(shiftvfrac[c], Ginthceil, Ginthfloor); - //if (rgb[indx][c]>clip_pt || Gtmp[indx]>clip_pt) continue; + //determine R/B at grid points using colour differences at shift point plus interpolated G value at grid point + //but first we need to interpolate G-R/G-B to grid points... + grbdiff[((rr)*ts + cc) >> 1] = Gint - rgb[c][(rr) * ts + cc]; + gshift[((rr)*ts + cc) >> 1] = Gint; + } + } - grbdiffold = rgb[1][indx] - rgb[c][indx]; + shifthfrac[0] /= 2.f; + shifthfrac[2] /= 2.f; + shiftvfrac[0] /= 2.f; + shiftvfrac[2] /= 2.f; - //interpolate color difference from optical R/B locations to grid locations - grbdiffinthfloor = (1.0f - shifthfrac[c] / 2.0f) * grbdiff[indx >> 1] + (shifthfrac[c] / 2.0f) * grbdiff[(indx - 2 * GRBdir[1][c]) >> 1]; - grbdiffinthceil = (1.0f - shifthfrac[c] / 2.0f) * grbdiff[((rr - 2 * GRBdir[0][c]) * TS + cc) >> 1] + (shifthfrac[c] / 2.0f) * grbdiff[((rr - 2 * GRBdir[0][c]) * TS + cc - 2 * GRBdir[1][c]) >> 1]; + // this loop does not deserve vectorization in mainly because the most expensive part with the divisions does not happen often (less than 1/10 in my tests) + for (int rr = 8; rr < rr1 - 8; rr++) + for (int cc = 8 + (FC(rr, 2) & 1), c = FC(rr, cc), indx = rr * ts + cc; cc < cc1 - 8; cc += 2, indx += 2) { + + float grbdiffold = rgb[1][indx] - rgb[c][indx]; + + //interpolate colour difference from optical R/B locations to grid locations + float grbdiffinthfloor = intp(shifthfrac[c], grbdiff[(indx - GRBdir[1][c]) >> 1], grbdiff[indx >> 1]); + float grbdiffinthceil = intp(shifthfrac[c], grbdiff[((rr - GRBdir[0][c]) * ts + cc - GRBdir[1][c]) >> 1], grbdiff[((rr - GRBdir[0][c]) * ts + cc) >> 1]); //grbdiffint is bilinear interpolation of G-R/G-B at grid point - grbdiffint = (1.0f - shiftvfrac[c] / 2.0f) * grbdiffinthfloor + (shiftvfrac[c] / 2.0f) * grbdiffinthceil; + float grbdiffint = intp(shiftvfrac[c], grbdiffinthceil, grbdiffinthfloor); - //now determine R/B at grid points using interpolated color differences and interpolated G value at grid point - RBint = rgb[1][indx] - grbdiffint; + //now determine R/B at grid points using interpolated colour differences and interpolated G value at grid point + float RBint = rgb[1][indx] - grbdiffint; if (fabsf(RBint - rgb[c][indx]) < 0.25f * (RBint + rgb[c][indx])) { if (fabsf(grbdiffold) > fabsf(grbdiffint) ) { @@ -1069,34 +970,33 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) } else { //gradient weights using difference from G at CA shift points and G at grid points - p[0] = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[indx >> 1])); - p[1] = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[(indx - 2 * GRBdir[1][c]) >> 1])); - p[2] = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[((rr - 2 * GRBdir[0][c]) * TS + cc) >> 1])); - p[3] = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[((rr - 2 * GRBdir[0][c]) * TS + cc - 2 * GRBdir[1][c]) >> 1])); + float p0 = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[indx >> 1])); + float p1 = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[(indx - GRBdir[1][c]) >> 1])); + float p2 = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[((rr - GRBdir[0][c]) * ts + cc) >> 1])); + float p3 = 1.0f / (eps + fabsf(rgb[1][indx] - gshift[((rr - GRBdir[0][c]) * ts + cc - GRBdir[1][c]) >> 1])); - grbdiffint = (p[0] * grbdiff[indx >> 1] + p[1] * grbdiff[(indx - 2 * GRBdir[1][c]) >> 1] + - p[2] * grbdiff[((rr - 2 * GRBdir[0][c]) * TS + cc) >> 1] + p[3] * grbdiff[((rr - 2 * GRBdir[0][c]) * TS + cc - 2 * GRBdir[1][c]) >> 1]) / (p[0] + p[1] + p[2] + p[3]); + grbdiffint = (p0 * grbdiff[indx >> 1] + p1 * grbdiff[(indx - GRBdir[1][c]) >> 1] + + p2 * grbdiff[((rr - GRBdir[0][c]) * ts + cc) >> 1] + p3 * grbdiff[((rr - GRBdir[0][c]) * ts + cc - GRBdir[1][c]) >> 1]) / (p0 + p1 + p2 + p3) ; - //now determine R/B at grid points using interpolated color differences and interpolated G value at grid point + //now determine R/B at grid points using interpolated colour differences and interpolated G value at grid point if (fabsf(grbdiffold) > fabsf(grbdiffint) ) { rgb[c][indx] = rgb[1][indx] - grbdiffint; } } - //if color difference interpolation overshot the correction, just desaturate + //if colour difference interpolation overshot the correction, just desaturate if (grbdiffold * grbdiffint < 0) { rgb[c][indx] = rgb[1][indx] - 0.5f * (grbdiffold + grbdiffint); } } // copy CA corrected results to temporary image matrix - for (rr = border; rr < rr1 - border; rr++) { - c = FC(rr + top, left + border + FC(rr + top, 2) & 1); + for (int rr = border; rr < rr1 - border; rr++) { + int c = FC(rr + top, left + border + FC(rr + top, 2) & 1); - for (row = rr + top, cc = border + (FC(rr, 2) & 1), indx = (row * width + cc + left) >> 1; cc < cc1 - border; cc += 2, indx++) { - col = cc + left; - RawDataTmp[indx] = 65535.0f * rgb[c][(rr) * TS + cc] + 0.5f; - //image[indx][c] = CLIP((int)(65535.0*rgb[(rr)*TS+cc][c] + 0.5));//for dcraw implementation + for (int row = rr + top, cc = border + (FC(rr, 2) & 1), indx = (row * width + cc + left) >> 1; cc < cc1 - border; cc += 2, indx++) { + int col = cc + left; + RawDataTmp[indx] = 65535.0f * rgb[c][(rr) * ts + cc] + 0.5f; } } @@ -1104,9 +1004,9 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) progresscounter++; if(progresscounter % 8 == 0) - #pragma omp critical + #pragma omp critical (cacorrect) { - progress += (double)(8.0 * (TS - border2) * (TS - border2)) / (2 * height * width); + progress += (double)(8.0 * (ts - border2) * (ts - border2)) / (2 * height * width); if (progress > 1.0) { progress = 1.0; @@ -1122,8 +1022,8 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) // copy temporary image matrix back to image matrix #pragma omp for - for(row = 0; row < height; row++) - for(col = 0 + (FC(row, 0) & 1), indx = (row * width + col) >> 1; col < width; col += 2, indx++) { + for(int row = 0; row < height; row++) + for(int col = 0 + (FC(row, 0) & 1), indx = (row * width + col) >> 1; col < width; col += 2, indx++) { rawData[row][col] = RawDataTmp[indx]; } @@ -1142,8 +1042,4 @@ void RawImageSource::CA_correct_RT(double cared, double cablue) if(plistener) { plistener->setProgress(1.0); } - -#undef TS -#undef TSH -#undef PIX_SORT } diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 682d6ff3f..597265bfe 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -7,7 +7,7 @@ link_directories ("${PROJECT_SOURCE_DIR}/rtexif" ${EXTRA_LIBDIR} ${GTHREAD_LIBRA set (CAMCONSTSFILE "camconst.json") -set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc dcraw.cc iccstore.cc color.cc +set (RTENGINESOURCEFILES colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc dcraw.cc iccstore.cc color.cc dfmanager.cc ffmanager.cc gauss.cc rawimage.cc image8.cc image16.cc imagefloat.cc imagedata.cc imageio.cc improcfun.cc init.cc dcrop.cc loadinitial.cc procparams.cc rawimagesource.cc demosaic_algos.cc shmap.cc simpleprocess.cc refreshmap.cc fast_demo.cc amaze_demosaic_RT.cc CA_correct_RT.cc cfa_linedn_RT.cc green_equil_RT.cc hilite_recon.cc expo_before_b.cc diff --git a/rtengine/LUT.h b/rtengine/LUT.h index 965180c92..418f90a23 100644 --- a/rtengine/LUT.h +++ b/rtengine/LUT.h @@ -52,6 +52,8 @@ * LUTf stands for LUT * LUTi stands for LUT * LUTu stands for LUT + * LUTd stands for LUT + * LUTuc stands for LUT */ #ifndef LUT_H_ @@ -65,6 +67,7 @@ #define LUTi LUT #define LUTu LUT #define LUTd LUT +#define LUTuc LUT #include #ifndef NDEBUG diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index e45a332e1..8290fe085 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -3,7 +3,6 @@ */ #include "camconst.h" #include "settings.h" -#include "safegtk.h" #include "rt_math.h" #include #include @@ -689,7 +688,7 @@ void CameraConstantsStore::init(Glib::ustring baseDir, Glib::ustring userSetting Glib::ustring userFile(Glib::build_filename(userSettingsDir, "camconst.json")); - if (safe_file_test(userFile, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(userFile, Glib::FILE_TEST_EXISTS)) { parse_camera_constants_file(userFile); } } diff --git a/rtengine/ciecam02.cc b/rtengine/ciecam02.cc index ec9d6722d..83ff98f95 100644 --- a/rtengine/ciecam02.cc +++ b/rtengine/ciecam02.cc @@ -328,7 +328,7 @@ double Ciecam02::calculate_fl_from_la_ciecam02( double la ) k = k * k; k = k * k; - return (0.2 * k * la5) + (0.1 * (1.0 - k) * (1.0 - k) * pow(la5, 1.0 / 3.0)); + return (0.2 * k * la5) + (0.1 * (1.0 - k) * (1.0 - k) * std::cbrt(la5)); } float Ciecam02::calculate_fl_from_la_ciecam02float( float la ) @@ -340,7 +340,7 @@ float Ciecam02::calculate_fl_from_la_ciecam02float( float la ) k = k * k; k = k * k; - return (0.2f * k * la5) + (0.1f * (1.0f - k) * (1.0f - k) * pow_F(la5, 1.0f / 3.0f)); + return (0.2f * k * la5) + (0.1f * (1.0f - k) * (1.0f - k) * std::cbrt(la5)); } double Ciecam02::achromatic_response_to_white( double x, double y, double z, double d, double fl, double nbb, int gamu ) diff --git a/rtengine/clutstore.cc b/rtengine/clutstore.cc index b36fd7dfb..a0ea5afb4 100644 --- a/rtengine/clutstore.cc +++ b/rtengine/clutstore.cc @@ -1,7 +1,6 @@ #include "clutstore.h" #include "rt_math.h" #include "stdimagesource.h" -#include "safegtk.h" #include "../rtgui/options.h" rtengine::CLUTStore clutStore; @@ -154,7 +153,7 @@ Imagefloat* HaldCLUT::loadFile( Glib::ustring filename, Glib::ustring workingCol Imagefloat *result = 0; StdImageSource imgSrc; - if ( !safe_file_test( filename, Glib::FILE_TEST_EXISTS ) || imgSrc.load(filename) ) { + if ( !Glib::file_test( filename, Glib::FILE_TEST_EXISTS ) || imgSrc.load(filename) ) { return result; } diff --git a/rtengine/color.cc b/rtengine/color.cc index c0dbab4d3..f5a8c86a3 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -36,6 +36,7 @@ LUTf Color::cachef; LUTf Color::gamma2curve; LUTf Color::gammatab; +LUTuc Color::gammatabThumb; LUTf Color::igammatab_srgb; LUTf Color::gammatab_srgb; // LUTf Color::igammatab_709; @@ -133,129 +134,204 @@ void MunsellDebugInfo::reinitValues() void Color::init () { - int maxindex = 65536; - cachef(maxindex, LUT_CLIP_BELOW); - - gamma2curve(maxindex, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); - - for (int i = 0; i < maxindex; i++) { - if (i > eps_max) { - cachef[i] = 327.68 * ( exp(1.0 / 3.0 * log((double)i / MAXVALF) )); - } else { - cachef[i] = 327.68 * ((kappa * i / MAXVALF + 16.0) / 116.0); - } - } - - for (int i = 0; i < maxindex; i++) { - gamma2curve[i] = (gamma2(i / 65535.0) * 65535.0); - } - /*******************************************/ - gammatab(65536, 0); - igammatab_srgb(65536, 0); - gammatab_srgb(65536, 0); - // igammatab_709(65536,0); - // gammatab_709(65536,0); - igammatab_55(65536, 0); - gammatab_55(65536, 0); - igammatab_4(65536, 0); - gammatab_4(65536, 0); + constexpr auto maxindex = 65536; - igammatab_26_11(65536, 0); - gammatab_26_11(65536, 0); - igammatab_24_17(65536, 0); - gammatab_24_17a(65536, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); - gammatab_13_2(65536, 0); - igammatab_13_2(65536, 0); - gammatab_115_2(65536, 0); - igammatab_115_2(65536, 0); - gammatab_145_3(65536, 0); - igammatab_145_3(65536, 0); + cachef(maxindex, LUT_CLIP_BELOW); + gamma2curve(maxindex, LUT_CLIP_BELOW | LUT_CLIP_ABOVE); + gammatab(maxindex, 0); + gammatabThumb(maxindex, 0); - for (int i = 0; i < 65536; i++) { - gammatab_srgb[i] = (65535.0 * gamma2 (i / 65535.0)); + igammatab_srgb(maxindex, 0); + gammatab_srgb(maxindex, 0); + igammatab_55(maxindex, 0); + gammatab_55(maxindex, 0); + igammatab_4(maxindex, 0); + gammatab_4(maxindex, 0); + + igammatab_26_11(maxindex, 0); + gammatab_26_11(maxindex, 0); + igammatab_24_17(maxindex, 0); + gammatab_24_17a(maxindex, LUT_CLIP_ABOVE | LUT_CLIP_BELOW); + gammatab_13_2(maxindex, 0); + igammatab_13_2(maxindex, 0); + gammatab_115_2(maxindex, 0); + igammatab_115_2(maxindex, 0); + gammatab_145_3(maxindex, 0); + igammatab_145_3(maxindex, 0); + +#ifdef _OPENMP + #pragma omp parallel sections +#endif + { +#ifdef _OPENMP + #pragma omp section +#endif + { + int i = 0; + int epsmaxint = eps_max; + + for (; i <= epsmaxint; i++) + { + cachef[i] = 327.68 * ((kappa * i / MAXVALF + 16.0) / 116.0); + } + + for(; i < maxindex; i++) + { + cachef[i] = 327.68 * std::cbrt((double)i / MAXVALF); + } + } +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_srgb[i] = gamma2curve[i] = 65535.0 * gamma2(i / 65535.0); // two lookup tables with same content but one clips and one does not clip + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_srgb[i] = 65535.0 * igamma2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + { + double rsRGBGamma = 1.0 / sRGBGamma; + + for (int i = 0; i < maxindex; i++) { + double val = pow (i / 65535.0, rsRGBGamma); + gammatab[i] = 65535.0 * val; + gammatabThumb[i] = (unsigned char)(255.0 * val); + } + } +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_55[i] = 65535.0 * gamma55 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_55[i] = 65535.0 * igamma55 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_4[i] = 65535.0 * gamma4 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_4[i] = 65535.0 * igamma4 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_13_2[i] = 65535.0 * gamma13_2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_13_2[i] = 65535.0 * igamma13_2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_115_2[i] = 65535.0 * gamma115_2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_115_2[i] = 65535.0 * igamma115_2 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_145_3[i] = 65535.0 * gamma145_3 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_145_3[i] = 65535.0 * igamma145_3 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_26_11[i] = 65535.0 * gamma26_11 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_26_11[i] = 65535.0 * igamma26_11 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + gammatab_24_17a[i] = gamma24_17(i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + + for (int i = 0; i < maxindex; i++) { + igammatab_24_17[i] = 65535.0 * igamma24_17 (i / 65535.0); + } + +#ifdef _OPENMP + #pragma omp section +#endif + initMunsell(); + +#ifdef _OPENMP + #pragma omp section +#endif + linearGammaTRC = cmsBuildGamma(NULL, 1.0); } - - for (int i = 0; i < 65536; i++) { - igammatab_srgb[i] = (65535.0 * igamma2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab[i] = (65535.0 * pow (i / 65535.0, 0.454545)); - } - - /* for (int i=0; i<65536; i++) - gammatab_709[i] = (65535.0 * gamma709 (i/65535.0)); - for (int i=0; i<65536; i++) - igammatab_709[i] = (65535.0 * igamma709 (i/65535.0)); - */ - for (int i = 0; i < 65536; i++) { - gammatab_55[i] = (65535.0 * gamma55 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_55[i] = (65535.0 * igamma55 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_4[i] = (65535.0 * gamma4 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_4[i] = (65535.0 * igamma4 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_13_2[i] = (65535.0 * gamma13_2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_13_2[i] = (65535.0 * igamma13_2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_115_2[i] = (65535.0 * gamma115_2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_115_2[i] = (65535.0 * igamma115_2 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_145_3[i] = (65535.0 * gamma145_3 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - igammatab_145_3[i] = (65535.0 * igamma145_3 (i / 65535.0)); - } - - for (int i = 0; i < 65536; i++) { - gammatab_26_11[i] = (65535.0 * gamma26_11 (i / 65535.0)); - } - -//gammatab_145_3 - 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++) - fprintf (f, "%g %g\n", i/255.0, clower (i/255.0, 2.0, 1.0)); - fclose (f);*/ - - initMunsell(); - - linearGammaTRC = cmsBuildGamma(NULL, 1.0); } void Color::cleanup () @@ -808,6 +884,15 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u float somm; float som = mixerRed + mixerGreen + mixerBlue; + if(som >= 0.f && som < 1.f) { + som = 1.f; + } + + if(som < 0.f && som > -1.f) { + som = -1.f; + } + + // rM = mixerRed, gM = mixerGreen, bM = mixerBlue ! //presets if (setting == "RGB-Abs" || setting == "ROYGCBPM-Abs") { @@ -869,6 +954,15 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u bbm = mixerBlue; somm = mixerRed + mixerGreen + mixerBlue; + + if(somm >= 0.f && somm < 1.f) { + somm = 1.f; + } + + if(somm < 0.f && somm > -1.f) { + somm = -1.f; + } + mixerRed = mixerRed / somm; mixerGreen = mixerGreen / somm; mixerBlue = mixerBlue / somm; @@ -1084,6 +1178,10 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u mixerGreen = mixerGreen * filgreen; mixerBlue = mixerBlue * filblue; + if(mixerRed + mixerGreen + mixerBlue == 0) { + mixerRed += 1.f; + } + mixerRed = filcor * mixerRed / (mixerRed + mixerGreen + mixerBlue); mixerGreen = filcor * mixerGreen / (mixerRed + mixerGreen + mixerBlue); mixerBlue = filcor * mixerBlue / (mixerRed + mixerGreen + mixerBlue); @@ -1091,6 +1189,14 @@ void Color::computeBWMixerConstants (const Glib::ustring &setting, const Glib::u if(filter != "None") { som = mixerRed + mixerGreen + mixerBlue; + if(som >= 0.f && som < 1.f) { + som = 1.f; + } + + if(som < 0.f && som > -1.f) { + som = -1.f; + } + if(setting == "RGB-Abs" || setting == "ROYGCBPM-Abs") { kcorec = kcorec * som; } @@ -1436,9 +1542,9 @@ void Color::Yuv2Lab(float Yin, float u, float v, float &L, float &a, float &b, d gamutmap(X, Y, Z, wp); - float fx = (X <= 65535.0 ? cachef[X] : (327.68 * exp(log(X / MAXVALF) / 3.0 ))); - float fy = (Y <= 65535.0 ? cachef[Y] : (327.68 * exp(log(Y / MAXVALF) / 3.0 ))); - float fz = (Z <= 65535.0 ? cachef[Z] : (327.68 * exp(log(Z / MAXVALF) / 3.0 ))); + float fx = (X <= 65535.0 ? cachef[X] : (327.68 * std::cbrt(X / MAXVALF))); + float fy = (Y <= 65535.0 ? cachef[Y] : (327.68 * std::cbrt(Y / MAXVALF))); + float fz = (Z <= 65535.0 ? cachef[Z] : (327.68 * std::cbrt(Z / MAXVALF))); L = (116.0 * fy - 5242.88); //5242.88=16.0*327.68; a = (500.0 * (fx - fy) ); @@ -1484,7 +1590,7 @@ void Color::XYZ2Luv (float X, float Y, float Z, float &L, float &u, float &v) Z /= 65535.f; if (Y > float(eps)) { - L = 116.f * pow(Y, 1.f / 3.f) - 16.f; + L = 116.f * std::cbrt(Y) - 16.f; } else { L = float(kappa) * Y; } diff --git a/rtengine/color.h b/rtengine/color.h index c179946f0..3f78692d8 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -130,8 +130,6 @@ public: // look-up tables for the standard srgb gamma and its inverse (filled by init()) static LUTf igammatab_srgb; static LUTf gammatab_srgb; -// static LUTf igammatab_709; -// static LUTf gammatab_709; static LUTf igammatab_55; static LUTf gammatab_55; static LUTf igammatab_4; @@ -150,6 +148,7 @@ public: // look-up tables for the simple exponential gamma static LUTf gammatab; + static LUTuc gammatabThumb; // for thumbnails static void init (); diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc index d4f1c995f..2ccbcba8d 100644 --- a/rtengine/colortemp.cc +++ b/rtengine/colortemp.cc @@ -1414,19 +1414,19 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, // xr, yr , zr > epsilon if(xr[i] > epsilon) { - fx[i] = pow(xr[i], 0.333); + fx[i] = std::cbrt(xr[i]); } else { fx[i] = (903.3 * xr[i] + 16.0) / 116.0; } if(yr[i] > epsilon) { - fy[i] = pow(yr[i], 0.333); + fy[i] = std::cbrt(yr[i]); } else { fy[i] = (903.3 * yr[i] + 16.0) / 116.0; } if(zr[i] > epsilon) { - fz[i] = pow(zr[i], 0.333); + fz[i] = std::cbrt(zr[i]); } else { fz[i] = (903.3 * zr[i] + 16.0) / 116.0; } @@ -1663,19 +1663,19 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, // xr, yr , zr > epsilon if(xr[i] > epsilon) { - fx[i] = pow(xr[i], 0.333); + fx[i] = std::cbrt(xr[i]); } else { fx[i] = (903.3 * xr[i] + 16.0) / 116.0; } if(yr[i] > epsilon) { - fy[i] = pow(yr[i], 0.333); + fy[i] = std::cbrt(yr[i]); } else { fy[i] = (903.3 * yr[i] + 16.0) / 116.0; } if(zr[i] > epsilon) { - fz[i] = pow(zr[i], 0.333); + fz[i] = std::cbrt(zr[i]); } else { fz[i] = (903.3 * zr[i] + 16.0) / 116.0; } @@ -1695,19 +1695,19 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, // if(xr[i] > epsilon) { - fx[i] = pow(xr[i], 0.333); + fx[i] = std::cbrt(xr[i]); } else { fx[i] = (903.3 * xr[i] + 16.0) / 116.0; } if(yr[i] > epsilon) { - fy[i] = pow(yr[i], 0.333); + fy[i] = std::cbrt(yr[i]); } else { fy[i] = (903.3 * yr[i] + 16.0) / 116.0; } if(zr[i] > epsilon) { - fz[i] = pow(zr[i], 0.333); + fz[i] = std::cbrt(zr[i]); } else { fz[i] = (903.3 * zr[i] + 16.0) / 116.0; } diff --git a/rtengine/coord.cc b/rtengine/coord.cc index c35d71e73..8a3d7d080 100644 --- a/rtengine/coord.cc +++ b/rtengine/coord.cc @@ -19,21 +19,49 @@ #include "coord.h" +#include "rt_math.h" + namespace rtengine { -void Coord::setFromPolar(PolarCoord polar) +Coord& Coord::operator= (const PolarCoord& other) { - while (polar.angle < 0.f) { - polar.angle += 360.f; - } + const auto radius = other.radius; + const auto angle = other.angle / 180.0 * M_PI; - while (polar.angle > 360.f) { - polar.angle -= 360.f; - } + x = radius * std::cos (angle); + y = radius * std::sin (angle); - x = polar.radius * cos(polar.angle / 180.f * M_PI); - y = polar.radius * sin(polar.angle / 180.f * M_PI); + return *this; +} + +PolarCoord& PolarCoord::operator= (const Coord& other) +{ + const double x = other.x; + const double y = other.y; + + radius = rtengine::norm2 (x, y); + angle = std::atan2 (y, x) * 180.0 / M_PI; + + return *this; +} + +/// @brief Clip the coord to stay in the width x height bounds +/// @return true if the x or y coordinate has changed +bool Coord::clip (const int width, const int height) +{ + const auto newX = rtengine::LIM (x, 0, width); + const auto newY = rtengine::LIM (y, 0, height); + + if (x != newX || y != newY) { + + x = newX; + y = newY; + + return true; + } else { + return false; + } } } diff --git a/rtengine/coord.h b/rtengine/coord.h index 359fb3a96..2242cec1e 100644 --- a/rtengine/coord.h +++ b/rtengine/coord.h @@ -16,205 +16,218 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ + #ifndef __COORD__ #define __COORD__ -#include "rt_math.h" - namespace rtengine { -class PolarCoord; +struct Coord; +struct PolarCoord; -// Do not confuse with rtengine::Coord2D, this one is for the GUI -class Coord +// Do not confuse with Coord2D, this one is used by the UI. +struct Coord { -public: - int x; - int y; + int x = 0; + int y = 0; - Coord() : x(-1), y(-1) {} - Coord(int x, int y) : x(x), y(y) {} + Coord () = default; + Coord (const int x, const int y); + Coord (const Coord& other) = default; + Coord (const PolarCoord& other); - void set (int x, int y) - { - this->x = x; - this->y = y; - } + Coord& operator= (const Coord& other) = default; + Coord& operator= (const PolarCoord& other); - void setFromPolar(PolarCoord polar); + void get (int& x, int& y) const; + void set (const int x, const int y); - /// @brief Clip the coord to stay in the width x height bounds - /// @return true if the x or y coordinate has changed - bool clip(int width, int height) - { - int trimmedX = rtengine::LIM(x, 0, width); - int trimmedY = rtengine::LIM(y, 0, height); - bool retval = trimmedX != x || trimmedY != y; - x = trimmedX; - y = trimmedY; - return retval; - } + bool clip (const int width, const int height); - bool operator== (const Coord& other) const - { - return other.x == x && other.y == y; - } - - bool operator!= (const Coord& other) const - { - return other.x != x || other.y != y; - } - - void operator+=(const Coord & rhs) - { - x += rhs.x; - y += rhs.y; - } - void operator-=(const Coord & rhs) - { - x -= rhs.x; - y -= rhs.y; - } - void operator*=(double scale) - { - x *= scale; - y *= scale; - } - Coord operator+(Coord & rhs) - { - Coord result(x + rhs.x, y + rhs.y); - return result; - } - Coord operator-(Coord & rhs) - { - Coord result(x - rhs.x, y - rhs.y); - return result; - } - Coord operator*(double scale) - { - Coord result(x * scale, y * scale); - return result; - } -}; - -class PolarCoord -{ -public: - double radius; - double angle; // degree - - PolarCoord() : radius(1.), angle(0.) {} - PolarCoord(double radius, double angle) : radius(radius), angle(angle) {} - PolarCoord(Coord start, Coord end) : radius(1.), angle(0.) - { - setFromCartesian(start, end); - } - PolarCoord(Coord delta) : radius(1.), angle(0.) - { - setFromCartesian(delta); - } - - void set (double radius, double angle) - { - this->radius = radius; - this->angle = angle; - } - - void setFromCartesian(Coord start, Coord end) - { - Coord delta(end.x - start.x, end.y - start.y); - setFromCartesian(delta); - } - - void setFromCartesian(Coord delta) - { - if (!delta.x && !delta.y) { - // null vector, we set to a default value - radius = 1.; - angle = 0.; - return; - } - - double x_ = double(delta.x); - double y_ = double(delta.y); - radius = sqrt(x_ * x_ + y_ * y_); - - if (delta.x > 0.) { - if (delta.y >= 0.) { - angle = atan(y_ / x_) / (2 * M_PI) * 360.; - } else if (delta.y < 0.) { - angle = (atan(y_ / x_) + 2 * M_PI) / (2 * M_PI) * 360.; - } - } else if (delta.x < 0.) { - angle = (atan(y_ / x_) + M_PI) / (2 * M_PI) * 360.; - } else if (delta.x == 0.) { - if (delta.y > 0.) { - angle = 90.; - } else { - angle = 270.; - } - } - } - - bool operator== (const PolarCoord& other) const - { - return other.radius == radius && other.angle == angle; - } - - bool operator!= (const PolarCoord& other) const - { - return other.radius != radius || other.angle != angle; - } - - void operator+=(const PolarCoord & rhs) - { - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord += rhsCoord; - setFromCartesian(thisCoord); - } - void operator-=(const PolarCoord & rhs) - { - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord -= rhsCoord; - setFromCartesian(thisCoord); - } - void operator*=(double scale) - { - radius *= scale; - } - PolarCoord operator+ (const PolarCoord& rhs) const - { - PolarCoord result; - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord += rhsCoord; - result.setFromCartesian(thisCoord); - return result; - } - PolarCoord operator- (const PolarCoord& rhs) const - { - PolarCoord result; - Coord thisCoord, rhsCoord; - thisCoord.setFromPolar(*this); - rhsCoord.setFromPolar(rhs); - thisCoord -= rhsCoord; - result.setFromCartesian(thisCoord); - return result; - } - Coord operator*(double scale) - { - Coord result(radius * scale, angle); - return result; - } + Coord& operator+= (const Coord& other); + Coord& operator-= (const Coord& other); + Coord& operator*= (const double scale); }; +bool operator== (const Coord& lhs, const Coord& rhs); +bool operator!= (const Coord& lhs, const Coord& rhs); + +const Coord operator+ (const Coord& lhs, const Coord& rhs); +const Coord operator- (const Coord& lhs, const Coord& rhs); +const Coord operator* (const Coord& lhs, const Coord& rhs); + +struct PolarCoord +{ + double radius = 0.0; + double angle = 0.0; + + PolarCoord () = default; + PolarCoord (const double radius, const double angle); + PolarCoord (const PolarCoord& other) = default; + PolarCoord (const Coord& other); + + PolarCoord& operator= (const PolarCoord& other) = default; + PolarCoord& operator= (const Coord& other); + + void get (double& radius, double& angle) const; + void set (const double radius, const double angle); + + PolarCoord& operator+= (const PolarCoord& other); + PolarCoord& operator-= (const PolarCoord& other); + PolarCoord& operator*= (const double scale); + +}; + +bool operator== (const PolarCoord& lhs, const PolarCoord& rhs); +bool operator!= (const PolarCoord& lhs, const PolarCoord& rhs); + +const PolarCoord operator+ (const PolarCoord& lhs, const PolarCoord& rhs); +const PolarCoord operator- (const PolarCoord& lhs, const PolarCoord& rhs); +const PolarCoord operator* (const PolarCoord& lhs, const double rhs); +const PolarCoord operator* (const double lhs, const PolarCoord& rhs); + +inline Coord::Coord (const int x, const int y) : x (x), y (y) +{ +} + +inline Coord::Coord (const PolarCoord& other) +{ + *this = other; +} + +inline void Coord::get (int& x, int& y) const +{ + x = this->x; + y = this->y; +} + +inline void Coord::set (const int x, const int y) +{ + this->x = x; + this->y = y; +} + +inline Coord& Coord::operator+= (const Coord& other) +{ + x += other.x; + y += other.y; + return *this; +} + +inline Coord& Coord::operator-= (const Coord& other) +{ + x -= other.x; + y -= other.y; + return *this; +} + +inline Coord& Coord::operator*= (const double scale) +{ + x *= scale; + y *= scale; + return *this; +} + +inline bool operator== (const Coord& lhs, const Coord& rhs) +{ + return lhs.x == rhs.x && lhs.y == rhs.y; +} + +inline bool operator!= (const Coord& lhs, const Coord& rhs) +{ + return !(lhs == rhs); +} + +inline const Coord operator+ (const Coord& lhs, const Coord& rhs) +{ + return Coord (lhs) += rhs; +} + +inline const Coord operator- (const Coord& lhs, const Coord& rhs) +{ + return Coord (lhs) -= rhs; +} + +inline const Coord operator* (const Coord& lhs, const double rhs) +{ + return Coord (lhs) *= rhs; +} + +inline const Coord operator* (const double lhs, const Coord& rhs) +{ + return Coord (rhs) *= lhs; +} + +inline PolarCoord::PolarCoord (const double radius, const double angle) : radius (radius), angle (angle) +{ +} + +inline PolarCoord::PolarCoord (const Coord& other) +{ + *this = other; +} + +inline void PolarCoord::get (double& radius, double& angle) const +{ + radius = this->radius; + angle = this->angle; +} + +inline void PolarCoord::set (const double radius, const double angle) +{ + this->radius = radius; + this->angle = angle; +} + +inline PolarCoord& PolarCoord::operator+= (const PolarCoord& other) +{ + *this = Coord (*this) + Coord (other); + return *this; +} + +inline PolarCoord &PolarCoord::operator-= (const PolarCoord &other) +{ + *this = Coord (*this) - Coord (other); + return *this; +} + +inline PolarCoord &PolarCoord::operator*= (const double scale) +{ + radius *= scale; + return *this; +} + +inline bool operator== (const PolarCoord& lhs, const PolarCoord& rhs) +{ + return lhs.radius == rhs.radius && lhs.angle == rhs.angle; +} + +inline bool operator!= (const PolarCoord& lhs, const PolarCoord& rhs) +{ + return !(lhs == rhs); +} + +inline const PolarCoord operator+ (const PolarCoord& lhs, const PolarCoord& rhs) +{ + return PolarCoord (lhs) += rhs; +} + +inline const PolarCoord operator- (const PolarCoord& lhs, const PolarCoord& rhs) +{ + return PolarCoord (lhs) -= rhs; +} + +inline const PolarCoord operator* (const PolarCoord& lhs, const double rhs) +{ + return PolarCoord (lhs) *= rhs; +} + +inline const PolarCoord operator* (const double lhs, const PolarCoord& rhs) +{ + return PolarCoord (rhs) *= lhs; +} } diff --git a/rtengine/curves.cc b/rtengine/curves.cc index d0b4c026f..6792df50d 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -34,6 +34,7 @@ #include "curves.h" #include "opthelper.h" #include "ciecam02.h" +#include "color.h" #undef CLIPD #define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) @@ -2293,7 +2294,7 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv { // increase chroma scaling slightly of shadows - float nL = gamma2curve[newLuminance]; // apply gamma so we make comparison and transition with a more perceptual lightness scale + float nL = Color::gamma2curve[newLuminance]; // apply gamma so we make comparison and transition with a more perceptual lightness scale float dark_scale_factor = 1.20f; //float dark_scale_factor = 1.0 + state.debug.p2 / 100.0f; const float lolim = 0.15f; @@ -2427,7 +2428,6 @@ void PerceptualToneCurve::Apply(float &r, float &g, float &b, PerceptualToneCurv float PerceptualToneCurve::cf_range[2]; float PerceptualToneCurve::cf[1000]; -LUTf PerceptualToneCurve::gamma2curve; float PerceptualToneCurve::f, PerceptualToneCurve::c, PerceptualToneCurve::nc, PerceptualToneCurve::yb, PerceptualToneCurve::la, PerceptualToneCurve::xw, PerceptualToneCurve::yw, PerceptualToneCurve::zw, PerceptualToneCurve::gamut; float PerceptualToneCurve::n, PerceptualToneCurve::d, PerceptualToneCurve::nbb, PerceptualToneCurve::ncb, PerceptualToneCurve::cz, PerceptualToneCurve::aw, PerceptualToneCurve::wh, PerceptualToneCurve::pfl, PerceptualToneCurve::fl, PerceptualToneCurve::pow1; @@ -2490,12 +2490,6 @@ void PerceptualToneCurve::init() cf_range[0] = in_x[0]; cf_range[1] = in_x[in_len - 1]; } - gamma2curve(65536, 0); - - for (int i = 0; i < 65536; i++) { - gamma2curve[i] = CurveFactory::gamma2(i / 65535.0); - } - } void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib::ustring workingSpace) const diff --git a/rtengine/curves.h b/rtengine/curves.h index fffd7dcb7..b0e9d691f 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -843,7 +843,6 @@ class PerceptualToneCurve : public ToneCurve private: static float cf_range[2]; static float cf[1000]; - static LUTf gamma2curve; // for ciecam02 static float f, c, nc, yb, la, xw, yw, zw, gamut; static float n, d, nbb, ncb, cz, aw, wh, pfl, fl, pow1; diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 9dd01330b..c05230738 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -19,7 +19,6 @@ #include #include "dcp.h" -#include "safegtk.h" #include "iccmatrices.h" #include "iccstore.h" #include "rawimagesource.h" @@ -828,7 +827,7 @@ DCPProfile::DCPProfile(Glib::ustring fname) aDeltas1 = aDeltas2 = aLookTable = NULL; - FILE *pFile = safe_g_fopen(fname, "rb"); + FILE *pFile = g_fopen(fname.c_str (), "rb"); TagDirectory *tagDir = ExifManager::parseTIFF(pFile, false); @@ -1717,7 +1716,7 @@ void DCPStore::init (Glib::ustring rtProfileDir) Glib::Dir* dir = NULL; try { - if (!safe_file_test (dirname, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (dirname, Glib::FILE_TEST_IS_DIR)) { return; } @@ -1733,7 +1732,7 @@ void DCPStore::init (Glib::ustring rtProfileDir) Glib::ustring sname = *i; // ignore directories - if (!safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { size_t lastdot = sname.find_last_of ('.'); if (lastdot != Glib::ustring::npos && lastdot <= sname.size() - 4 && (!sname.casefold().compare (lastdot, 4, ".dcp"))) { @@ -1781,7 +1780,7 @@ DCPProfile* DCPStore::getStdProfile(Glib::ustring camShortName) bool DCPStore::isValidDCPFileName(Glib::ustring filename) const { - if (!safe_file_test (filename, Glib::FILE_TEST_EXISTS) || safe_file_test (filename, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (filename, Glib::FILE_TEST_EXISTS) || Glib::file_test (filename, Glib::FILE_TEST_IS_DIR)) { return false; } diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 89e39c1da..77f0598b4 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -705,6 +705,17 @@ void Crop::update (int todo) transCrop = NULL; } + if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) { + + const int W = baseCrop->getWidth(); + const int H = baseCrop->getHeight(); + LabImage labcbdl(W, H); + parent->ipf.rgb2lab(*baseCrop, labcbdl, params.icm.working); + parent->ipf.dirpyrequalizer (&labcbdl, skip); + parent->ipf.lab2rgb(labcbdl, *baseCrop, params.icm.working); + + } + // blurmap for shadow & highlights if ((todo & M_BLURMAP) && params.sh.enabled) { double radius = sqrt (double(SKIPS(parent->fw, skip) * SKIPS(parent->fw, skip) + SKIPS(parent->fh, skip) * SKIPS(parent->fh, skip))) / 2.0; @@ -725,6 +736,7 @@ void Crop::update (int todo) } } + // shadows & highlights & tone curve & convert to cielab /*int xref,yref; xref=000;yref=000; @@ -831,12 +843,13 @@ void Crop::update (int todo) // if (skip==1) { WaveletParams WaveParams = params.wavelet; - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - parent->ipf.dirpyrequalizer (labnCrop, skip); - // parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip); + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled))) { + parent->ipf.dirpyrequalizer (labnCrop, skip); + // parent->ipf.Lanczoslab (labnCrop,labnCrop , 1.f/skip); + } } - int kall = 0; int minwin = min(labnCrop->W, labnCrop->H); int maxlevelcrop = 10; diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index f8036f24e..8774ce9f0 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -90,17 +90,17 @@ void RawImageSource::eahd_demosaic () threshold = (int)(0.008856 * MAXVALD); for (int i = 0; i < maxindex; i++) { - cache[i] = exp(1.0 / 3.0 * log(double(i) / MAXVALD)); + cache[i] = std::cbrt(double(i) / MAXVALD); } // end of cielab preparation const JaggedArray - rh (W, 3), gh (W, 4), bh (W, 3), - rv (W, 3), gv (W, 4), bv (W, 3), - lLh (W, 3), lah (W, 3), lbh (W, 3), - lLv (W, 3), lav (W, 3), lbv (W, 3), - homh (W, 3), homv (W, 3); + rh (W, 3), gh (W, 4), bh (W, 3), + rv (W, 3), gv (W, 4), bv (W, 3), + lLh (W, 3), lah (W, 3), lbh (W, 3), + lLv (W, 3), lav (W, 3), lbv (W, 3), + homh (W, 3), homv (W, 3); // interpolate first two lines interpolate_row_g (gh[0], gv[0], 0); @@ -2703,7 +2703,7 @@ void RawImageSource::ahd_demosaic(int winx, int winy, int winw, int winh) for (i = 0; i < 0x10000; i++) { r = (double)i / 65535.0; - cbrt[i] = r > 0.008856 ? pow(r, 0.333333333) : 7.787 * r + 16 / 116.0; + cbrt[i] = r > 0.008856 ? std::cbrt(r) : 7.787 * r + 16 / 116.0; } for (i = 0; i < 3; i++) diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index cc9bafc4d..7189fbe40 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -20,7 +20,6 @@ #include "../rtgui/options.h" #include #include "../rtgui/guiutils.h" -#include "safegtk.h" #include "rawimage.h" #include #include @@ -263,13 +262,21 @@ void dfInfo::updateBadPixelList( RawImage *df ) void DFManager::init( Glib::ustring pathname ) { std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path (pathname); - if( dir && !dir->query_exists()) { + auto dir = Gio::File::create_for_path (pathname); + if (!dir || !dir->query_exists()) { return; } - safe_build_file_list (dir, names, pathname); + try { + + auto enumerator = dir->enumerate_children ("standard::name"); + + while (auto file = enumerator->next_file ()) { + names.emplace_back (Glib::build_filename (pathname, file->get_name ())); + } + + } catch (Glib::Exception&) {} dfList.clear(); bpList.clear(); @@ -320,65 +327,84 @@ void DFManager::init( Glib::ustring pathname ) return; } -dfInfo *DFManager::addFileInfo(const Glib::ustring &filename , bool pool ) +dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool) { - Glib::RefPtr file = Gio::File::create_for_path(filename); + auto file = Gio::File::create_for_path (filename); - if (!file ) { + if (!file) { return 0; } - if( !file->query_exists()) { + if (!file->query_exists ()) { return 0; } - Glib::RefPtr info = safe_query_file_info(file); + try { - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); + auto info = file->query_info (); - if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { - RawImage ri(filename); - int res = ri.loadRaw(false); // Read informations about shot + if (!info && info->get_file_type () == Gio::FILE_TYPE_DIRECTORY) { + return 0; + } - if( !res ) { - dfList_t::iterator iter; + if (!options.fbShowHidden && info->is_hidden ()) { + return 0; + } - if(!pool) { - dfInfo n(filename, "", "", 0, 0, 0); - iter = dfList.insert(std::pair< std::string, dfInfo>( "", n ) ); - return &(iter->second); - } + Glib::ustring ext; - RawMetaDataLocation rml; - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - ImageData idata(filename, &rml); - /* Files are added in the map, divided by same maker/model,ISO and shutter*/ - std::string key( dfInfo::key(((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed()) ); - iter = dfList.find( key ); + auto lastdot = info->get_name ().find_last_of ('.'); + if (lastdot != Glib::ustring::npos) { + ext = info->get_name ().substr (lastdot + 1); + } - if( iter == dfList.end() ) { - dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS() ); - iter = dfList.insert(std::pair< std::string, dfInfo>( key, n ) ); - } else { - while( iter != dfList.end() && iter->second.key() == key && ABS(iter->second.timestamp - idata.getDateTimeAsTS()) > 60 * 60 * 6 ) { // 6 hour difference - iter++; - } + if (!options.is_extention_enabled (ext)) { + return 0; + } - if( iter != dfList.end() ) { - iter->second.pathNames.push_back( filename ); - } else { - dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS()); - iter = dfList.insert(std::pair< std::string, dfInfo>( key, n ) ); - } - } + RawImage ri (filename); + int res = ri.loadRaw (false); // Read informations about shot - return &(iter->second); + if (res != 0) { + return 0; + } + + dfList_t::iterator iter; + + if(!pool) { + dfInfo n(filename, "", "", 0, 0, 0); + iter = dfList.insert(std::pair< std::string, dfInfo>( "", n ) ); + return &(iter->second); + } + + RawMetaDataLocation rml; + rml.exifBase = ri.get_exifBase(); + rml.ciffBase = ri.get_ciffBase(); + rml.ciffLength = ri.get_ciffLen(); + ImageData idata(filename, &rml); + /* Files are added in the map, divided by same maker/model,ISO and shutter*/ + std::string key( dfInfo::key(((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed()) ); + iter = dfList.find( key ); + + if( iter == dfList.end() ) { + dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS() ); + iter = dfList.insert(std::pair< std::string, dfInfo>( key, n ) ); + } else { + while( iter != dfList.end() && iter->second.key() == key && ABS(iter->second.timestamp - idata.getDateTimeAsTS()) > 60 * 60 * 6 ) { // 6 hour difference + iter++; + } + + if( iter != dfList.end() ) { + iter->second.pathNames.push_back( filename ); + } else { + dfInfo n(filename, ((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS()); + iter = dfList.insert(std::pair< std::string, dfInfo>( key, n ) ); } } - } + + return &(iter->second); + + } catch(Gio::Error&) {} return 0; } diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index c311361e6..783c18bf7 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -19,7 +19,6 @@ #include "ffmanager.h" #include "../rtgui/options.h" #include -#include "safegtk.h" #include "rawimage.h" #include #include @@ -209,13 +208,21 @@ void ffInfo::updateRawImage() void FFManager::init( Glib::ustring pathname ) { std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path (pathname); - if( dir && !dir->query_exists()) { + auto dir = Gio::File::create_for_path (pathname); + if (!dir || !dir->query_exists()) { return; } - safe_build_file_list (dir, names, pathname); + try { + + auto enumerator = dir->enumerate_children ("standard::name"); + + while (auto file = enumerator->next_file ()) { + names.emplace_back (Glib::build_filename (pathname, file->get_name ())); + } + + } catch (Glib::Exception&) {} ffList.clear(); @@ -253,65 +260,85 @@ void FFManager::init( Glib::ustring pathname ) return; } -ffInfo *FFManager::addFileInfo(const Glib::ustring &filename, bool pool ) +ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool) { - Glib::RefPtr file = Gio::File::create_for_path(filename); + auto file = Gio::File::create_for_path (filename); if (!file ) { return 0; } - if( !file->query_exists()) { + if (!file->query_exists ()) { return 0; } - Glib::RefPtr info = safe_query_file_info(file); + try { - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); + auto info = file->query_info (); - if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { - RawImage ri(filename); - int res = ri.loadRaw(false); // Read informations about shot + if (!info || info->get_file_type () == Gio::FILE_TYPE_DIRECTORY) { + return 0; + } - if( !res ) { - ffList_t::iterator iter; + if (!options.fbShowHidden && info->is_hidden ()) { + return 0; + } - if(!pool) { - ffInfo n(filename, "", "", "", 0, 0, 0); - iter = ffList.insert(std::pair< std::string, ffInfo>( "", n ) ); - return &(iter->second); - } + Glib::ustring ext; - RawMetaDataLocation rml; - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - ImageData idata(filename, &rml); - /* Files are added in the map, divided by same maker/model,lens and aperture*/ - std::string key( ffInfo::key(idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber()) ); - iter = ffList.find( key ); + auto lastdot = info->get_name ().find_last_of ('.'); + if (lastdot != Glib::ustring::npos) { + ext = info->get_name ().substr (lastdot + 1); + } - if( iter == ffList.end() ) { - ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS()); - iter = ffList.insert(std::pair< std::string, ffInfo>( key, n ) ); - } else { - while( iter != ffList.end() && iter->second.key() == key && ABS(iter->second.timestamp - ri.get_timestamp()) > 60 * 60 * 6 ) { // 6 hour difference - iter++; - } + if (!options.is_extention_enabled (ext)) { + return 0; + } - if( iter != ffList.end() ) { - iter->second.pathNames.push_back( filename ); - } else { - ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS()); - iter = ffList.insert(std::pair< std::string, ffInfo>( key, n ) ); - } - } - return &(iter->second); + RawImage ri (filename); + int res = ri.loadRaw (false); // Read informations about shot + + if (res != 0) { + return 0; + } + + ffList_t::iterator iter; + + if(!pool) { + ffInfo n(filename, "", "", "", 0, 0, 0); + iter = ffList.insert(std::pair< std::string, ffInfo>( "", n ) ); + return &(iter->second); + } + + RawMetaDataLocation rml; + rml.exifBase = ri.get_exifBase(); + rml.ciffBase = ri.get_ciffBase(); + rml.ciffLength = ri.get_ciffLen(); + ImageData idata(filename, &rml); + /* Files are added in the map, divided by same maker/model,lens and aperture*/ + std::string key( ffInfo::key(idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber()) ); + iter = ffList.find( key ); + + if( iter == ffList.end() ) { + ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS()); + iter = ffList.insert(std::pair< std::string, ffInfo>( key, n ) ); + } else { + while( iter != ffList.end() && iter->second.key() == key && ABS(iter->second.timestamp - ri.get_timestamp()) > 60 * 60 * 6 ) { // 6 hour difference + iter++; + } + + if( iter != ffList.end() ) { + iter->second.pathNames.push_back( filename ); + } else { + ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS()); + iter = ffList.insert(std::pair< std::string, ffInfo>( key, n ) ); } } - } + + return &(iter->second); + + } catch (Gio::Error&) {} return 0; } diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index ff29c72ab..cb5314489 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -16,18 +16,21 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include "iccstore.h" + +#include + #ifdef WIN32 #include #else #include #endif -#include "iccstore.h" -#include "iccmatrices.h" -#include -#include "safegtk.h" -#include "../rtgui/options.h" -#include +#include + +#include "iccmatrices.h" + +#include "../rtgui/options.h" namespace { @@ -59,7 +62,7 @@ void loadProfiles (const Glib::ustring& dirName, const Glib::ustring filePath = Glib::build_filename (dirName, fileName); - if (!safe_file_test (filePath, Glib::FILE_TEST_IS_REGULAR)) + if (!Glib::file_test (filePath, Glib::FILE_TEST_IS_REGULAR)) continue; Glib::ustring name = fileName.substr (0, fileName.size() - 4); @@ -356,8 +359,9 @@ cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const const ProfileMap::const_iterator r = fileProfiles.find (name); - if (r != fileProfiles.end ()) + if (r != fileProfiles.end ()) { return r->second; + } if (name.compare (0, 5, "file:") == 0) { const ProfileContent content (name.substr (5)); @@ -371,7 +375,7 @@ cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const } } - return NULL; + return nullptr; } cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) const @@ -418,7 +422,6 @@ ProfileContent ICCStore::getContent (const Glib::ustring& name) const std::uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) const { - MyMutex::MyLock lock (mutex_); return getSupportedIntents (profile, LCMS_USED_AS_INPUT); @@ -426,7 +429,6 @@ std::uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) const std::uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) const { - MyMutex::MyLock lock (mutex_); return getSupportedIntents (profile, LCMS_USED_AS_OUTPUT); @@ -434,7 +436,6 @@ std::uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) const std::uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) const { - MyMutex::MyLock lock (mutex_); return getSupportedIntents (profile, LCMS_USED_AS_PROOF); @@ -503,7 +504,7 @@ void ICCStore::findDefaultMonitorProfile () ProfileContent::ProfileContent (const Glib::ustring& fileName) : data(NULL), length(0) { - FILE* f = safe_g_fopen (fileName, "rb"); + FILE* f = g_fopen (fileName.c_str (), "rb"); if (!f) { return; diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 93c6b6604..c0da10761 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -19,12 +19,25 @@ #include "imagedata.h" #include "iptcpairs.h" #include -#include "safegtk.h" using namespace rtengine; extern "C" IptcData *iptc_data_new_from_jpeg_file (FILE* infile); +namespace +{ + +Glib::ustring to_utf8 (const std::string& str) +{ + try { + return Glib::locale_to_utf8 (str); + } catch (Glib::Error&) { + return Glib::convert_with_fallback (str, "UTF-8", "ISO-8859-1", "?"); + } +} + +} + ImageMetaData* ImageMetaData::fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml) { @@ -39,7 +52,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) iptc = NULL; if (ri && (ri->exifBase >= 0 || ri->ciffBase >= 0)) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { if (ri->exifBase >= 0) { @@ -60,18 +73,18 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) extractInfo (); } } else if ((dotpos < fname.size() - 3 && !fname.casefold().compare (dotpos, 4, ".jpg")) || (dotpos < fname.size() - 4 && !fname.casefold().compare (dotpos, 5, ".jpeg"))) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { root = rtexif::ExifManager::parseJPEG (f); extractInfo (); fclose (f); - FILE* ff = safe_g_fopen (fname, "rb"); + FILE* ff = g_fopen (fname.c_str (), "rb"); iptc = iptc_data_new_from_jpeg_file (ff); fclose (ff); } } else if ((dotpos < fname.size() - 3 && !fname.casefold().compare (dotpos, 4, ".tif")) || (dotpos < fname.size() - 4 && !fname.casefold().compare (dotpos, 5, ".tiff"))) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { root = rtexif::ExifManager::parseTIFF (f); @@ -271,176 +284,183 @@ void ImageData::extractInfo () } else if(!make.compare (0, 4, "SONY")) { if (iso_speed == 65535 || iso_speed == 0) { rtexif::Tag* isoTag = exif->getTag ("RecommendedExposureIndex"); - if(isoTag) + + if(isoTag) { iso_speed = isoTag->toDouble(); + } } } - else if (root->findTag("MakerNote")) { - rtexif::TagDirectory* mnote = root->findTag("MakerNote")->getDirectory(); - if (mnote && !make.compare (0, 5, "NIKON")) { - // ISO at max value supported, check manufacturer specific - if (iso_speed == 65535 || iso_speed == 0) { - rtexif::Tag* isoTag = mnote->getTagP("ISOInfo/ISO"); + if (lens == "Unknown") { + rtexif::Tag* mnoteTag = root->findTag("MakerNote"); - if (isoTag) { - iso_speed = isoTag->toInt(); + if (mnoteTag) { + rtexif::TagDirectory* mnote = mnoteTag->getDirectory(); + + if (mnote && !make.compare (0, 5, "NIKON")) { + // ISO at max value supported, check manufacturer specific + if (iso_speed == 65535 || iso_speed == 0) { + rtexif::Tag* isoTag = mnote->getTagP("ISOInfo/ISO"); + + if (isoTag) { + iso_speed = isoTag->toInt(); + } } - } - bool lensOk = false; + bool lensOk = false; - if (mnote->getTag ("LensData")) { - std::string ldata = mnote->getTag ("LensData")->valueToString (); - int pos; + if (mnote->getTag ("LensData")) { + std::string ldata = mnote->getTag ("LensData")->valueToString (); + int pos; - if (ldata.size() > 10 && (pos = ldata.find ("Lens = ")) != Glib::ustring::npos) { - lens = ldata.substr (pos + 7); + if (ldata.size() > 10 && (pos = ldata.find ("Lens = ")) != Glib::ustring::npos) { + lens = ldata.substr (pos + 7); - if (lens.compare (0, 7, "Unknown")) { - lensOk = true; - } else { - int pos = lens.find("$FL$"); // is there a placeholder for focallength? + if (lens.compare (0, 7, "Unknown")) { + lensOk = true; + } else { + int pos = lens.find("$FL$"); // is there a placeholder for focallength? - if(pos != Glib::ustring::npos) { // then fill in focallength - lens = lens.replace(pos, 4, exif->getTag ("FocalLength")->valueToString ()); + if(pos != Glib::ustring::npos) { // then fill in focallength + lens = lens.replace(pos, 4, exif->getTag ("FocalLength")->valueToString ()); - if(mnote->getTag ("LensType")) { - std::string ltype = mnote->getTag ("LensType")->valueToString (); + if(mnote->getTag ("LensType")) { + std::string ltype = mnote->getTag ("LensType")->valueToString (); - if(ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens, should be always - lens = lens.replace(0, 7, "MF"); + if(ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens, should be always + lens = lens.replace(0, 7, "MF"); + } + + lensOk = true; } - - lensOk = true; } } } } - } - if (!lensOk && mnote->getTag ("Lens")) { - std::string ldata = mnote->getTag ("Lens")->valueToString (); - size_t i = 0, j = 0; - double n[4]; + if (!lensOk && mnote->getTag ("Lens")) { + std::string ldata = mnote->getTag ("Lens")->valueToString (); + size_t i = 0, j = 0; + double n[4]; - for (int m = 0; m < 4; m++) { - while (i < ldata.size() && ldata[i] != '/') { + for (int m = 0; m < 4; m++) { + while (i < ldata.size() && ldata[i] != '/') { + i++; + } + + int nom = atoi(ldata.substr(j, i).c_str()); + j = i + 1; i++; + + while (i < ldata.size() && ldata[i] != ',') { + i++; + } + + int den = atoi(ldata.substr(j, i).c_str()); + j = i + 2; + i += 2; + n[m] = (double) nom / den; } - int nom = atoi(ldata.substr(j, i).c_str()); - j = i + 1; - i++; + std::ostringstream str; - while (i < ldata.size() && ldata[i] != ',') { - i++; - } - - int den = atoi(ldata.substr(j, i).c_str()); - j = i + 2; - i += 2; - n[m] = (double) nom / den; - } - - std::ostringstream str; - - if (n[0] == n[1]) { - str << "Unknown " << n[0] << "mm F/" << n[2]; - } else if (n[2] == n[3]) { - str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2]; - } else { - str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2] << "-" << n[3]; - } - - lens = str.str(); - - // Look whether it's MF or AF - if(mnote->getTag ("LensType")) { - std::string ltype = mnote->getTag ("LensType")->valueToString (); - - if(ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens - lens = lens.replace(0, 7, "MF"); // replace 'Unknwon' with 'MF' + if (n[0] == n[1]) { + str << "Unknown " << n[0] << "mm F/" << n[2]; + } else if (n[2] == n[3]) { + str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2]; } else { - lens = lens.replace(0, 7, "AF"); // replace 'Unknwon' with 'AF' + str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2] << "-" << n[3]; + } + + lens = str.str(); + + // Look whether it's MF or AF + if(mnote->getTag ("LensType")) { + std::string ltype = mnote->getTag ("LensType")->valueToString (); + + if(ltype.find("MF = Yes") != Glib::ustring::npos) { // check, whether it's a MF lens + lens = lens.replace(0, 7, "MF"); // replace 'Unknwon' with 'MF' + } else { + lens = lens.replace(0, 7, "AF"); // replace 'Unknwon' with 'AF' + } } } - } - } else if (mnote && !make.compare (0, 5, "Canon")) { - // ISO at max value supported, check manufacturer specific - if (iso_speed == 65535 || iso_speed == 0) { - rtexif::Tag* baseIsoTag = mnote->getTagP("CanonShotInfo/BaseISO"); + } else if (mnote && !make.compare (0, 5, "Canon")) { + // ISO at max value supported, check manufacturer specific + if (iso_speed == 65535 || iso_speed == 0) { + rtexif::Tag* baseIsoTag = mnote->getTagP("CanonShotInfo/BaseISO"); - if (baseIsoTag) { - iso_speed = baseIsoTag->toInt(); + if (baseIsoTag) { + iso_speed = baseIsoTag->toInt(); + } } - } - int found = false; - // canon EXIF have a string for lens model - rtexif::Tag *lt = mnote->getTag("LensType"); - - if ( lt ) { - std::string ldata = lt->valueToString (); - - if (ldata.size() > 1) { - found = true; - lens = "Canon " + ldata; - } - } - - if( !found || lens.substr(lens.find(' ')).length() < 7 ) { - lt = mnote->findTag("LensID"); + int found = false; + // canon EXIF have a string for lens model + rtexif::Tag *lt = mnote->getTag("LensType"); if ( lt ) { std::string ldata = lt->valueToString (); if (ldata.size() > 1) { - lens = ldata; + found = true; + lens = "Canon " + ldata; + } + } + + if( !found || lens.substr(lens.find(' ')).length() < 7 ) { + lt = mnote->findTag("LensID"); + + if ( lt ) { + std::string ldata = lt->valueToString (); + + if (ldata.size() > 1) { + lens = ldata; + } + } + } + } else if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { + if (mnote->getTag ("LensType")) { + lens = mnote->getTag ("LensType")->valueToString (); + } + + // Try to get the FocalLength from the LensInfo structure, where length below 10mm will be correctly set + rtexif::Tag* flt = mnote->getTagP ("LensInfo/FocalLength"); + + if (flt) { + // Don't replace Exif focal_len if Makernotes focal_len is 0 + if (flt->toDouble() > 0) { + focal_len = flt->toDouble (); + } + } else if ((flt = mnote->getTagP ("FocalLength"))) { + rtexif::Tag* flt = mnote->getTag ("FocalLength"); + focal_len = flt->toDouble (); + } + + if (mnote->getTag ("FocalLengthIn35mmFilm")) { + focal_len35mm = mnote->getTag ("FocalLengthIn35mmFilm")->toDouble (); + } + } else if (mnote && (!make.compare (0, 4, "SONY") || !make.compare (0, 6, "KONICA"))) { + if (mnote->getTag ("LensID")) { + lens = mnote->getTag ("LensID")->valueToString (); + } + } else if (mnote && !make.compare (0, 7, "OLYMPUS")) { + if (mnote->getTag ("Equipment")) { + rtexif::TagDirectory* eq = mnote->getTag ("Equipment")->getDirectory (); + + if (eq->getTag ("LensType")) { + lens = eq->getTag ("LensType")->valueToString (); } } } - } else if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { - if (mnote->getTag ("LensType")) { - lens = mnote->getTag ("LensType")->valueToString (); - } - - // Try to get the FocalLength from the LensInfo structure, where length below 10mm will be correctly set - rtexif::Tag* flt = mnote->getTagP ("LensInfo/FocalLength"); - - if (flt) { - // Don't replace Exif focal_len if Makernotes focal_len is 0 - if (flt->toDouble() > 0) { - focal_len = flt->toDouble (); - } - } else if ((flt = mnote->getTagP ("FocalLength"))) { - rtexif::Tag* flt = mnote->getTag ("FocalLength"); - focal_len = flt->toDouble (); - } - - if (mnote->getTag ("FocalLengthIn35mmFilm")) { - focal_len35mm = mnote->getTag ("FocalLengthIn35mmFilm")->toDouble (); - } - } else if (mnote && (!make.compare (0, 4, "SONY") || !make.compare (0, 6, "KONICA"))) { - if (mnote->getTag ("LensID")) { - lens = mnote->getTag ("LensID")->valueToString (); - } - } else if (mnote && !make.compare (0, 7, "OLYMPUS")) { - if (mnote->getTag ("Equipment")) { - rtexif::TagDirectory* eq = mnote->getTag ("Equipment")->getDirectory (); - - if (eq->getTag ("LensType")) { - lens = eq->getTag ("LensType")->valueToString (); - } - } + } else if (exif->getTag ("DNGLensInfo")) { + lens = exif->getTag ("DNGLensInfo")->valueToString (); + } else if (exif->getTag ("LensModel")) { + lens = exif->getTag ("LensModel")->valueToString (); + } else if (exif->getTag ("LensInfo")) { + lens = exif->getTag ("LensInfo")->valueToString (); } - } else if (exif->getTag ("DNGLensInfo")) { - lens = exif->getTag ("DNGLensInfo")->valueToString (); - } else if (exif->getTag ("LensModel")) { - lens = exif->getTag ("LensModel")->valueToString (); - } else if (exif->getTag ("LensInfo")) { - lens = exif->getTag ("LensInfo")->valueToString (); } } } @@ -472,7 +492,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const if (ds) { iptc_dataset_get_data (ds, buffer, 2100); std::vector icValues; - icValues.push_back (safe_locale_to_utf8((char*)buffer)); + icValues.push_back (to_utf8((char*)buffer)); iptcc[strTags[i].field] = icValues; iptc_dataset_unref (ds); @@ -484,7 +504,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const while ((ds = iptc_data_get_next_dataset (iptc, ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS))) { iptc_dataset_get_data (ds, buffer, 2100); - keywords.push_back (safe_locale_to_utf8((char*)buffer)); + keywords.push_back (to_utf8((char*)buffer)); } iptcc["Keywords"] = keywords; @@ -493,7 +513,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const while ((ds = iptc_data_get_next_dataset (iptc, ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY))) { iptc_dataset_get_data (ds, buffer, 2100); - suppCategories.push_back (safe_locale_to_utf8((char*)buffer)); + suppCategories.push_back (to_utf8((char*)buffer)); iptc_dataset_unref (ds); } diff --git a/rtengine/imagedimensions.h b/rtengine/imagedimensions.h index 0b50d71c1..e3b98f7c5 100644 --- a/rtengine/imagedimensions.h +++ b/rtengine/imagedimensions.h @@ -48,11 +48,11 @@ public: { return height; } - int getWidth () + int getWidth () const { return width; } - int getHeight () + int getHeight () const { return height; } diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index db289ca1a..4fa5a5a93 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -36,7 +36,6 @@ #endif #include "imageio.h" -#include "safegtk.h" #include "iptcpairs.h" #include "iccjpeg.h" #include "color.h" @@ -47,9 +46,46 @@ using namespace std; using namespace rtengine; using namespace rtengine::procparams; -Glib::ustring safe_locale_to_utf8 (const std::string& src); -Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.", "Error while reading header.", "File reading error", "Image format not supported."}; +namespace +{ +// Opens a file for binary writing and request exclusive lock (cases were you need "wb" mode plus locking) +FILE* g_fopen_withBinaryAndLock(const Glib::ustring& fname) +{ + FILE* f = NULL; + +#ifdef WIN32 + + // Use native function to disallow sharing, i.e. lock the file for exclusive access. + // This is important to e.g. prevent Windows Explorer from crashing RT due to concurrently scanning an image file. + std::unique_ptr wfname (reinterpret_cast(g_utf8_to_utf16 (fname.c_str (), -1, NULL, NULL, NULL)), g_free); + + HANDLE hFile = CreateFileW ( wfname.get (), GENERIC_READ | GENERIC_WRITE, 0 /* no sharing allowed */, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + f = _fdopen (_open_osfhandle ((intptr_t)hFile, 0), "wb"); + } + +#else + + f = ::g_fopen (fname.c_str (), "wb"); + +#endif + + return f; +} + +Glib::ustring to_utf8 (const std::string& str) +{ + try { + return Glib::locale_to_utf8 (str); + } catch (Glib::Error&) { + return Glib::convert_with_fallback (str, "UTF-8", "ISO-8859-1", "?"); + } +} + +} + +Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.", "Error while reading header.", "File reading error", "Image format not supported."}; // For only copying the raw input data void ImageIO::setMetadata (const rtexif::TagDirectory* eroot) @@ -77,12 +113,6 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr // store exif info exifChange.clear(); exifChange = exif; - /*unsigned int j=0; - for (rtengine::procparams::ExifPairs::const_iterator i=exif.begin(); i!=exif.end(); i++) { - exifChange.at(j).first = i->first; - exifChange.at(j).second = i->second; - j++; - }*/ if (exifRoot != NULL) { delete exifRoot; @@ -110,7 +140,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr for (unsigned int j = 0; j < i->second.size(); j++) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS); - std::string loc = safe_locale_to_utf8(i->second.at(j)); + std::string loc = to_utf8(i->second.at(j)); iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(static_cast(64), loc.size()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); @@ -121,7 +151,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr for (unsigned int j = 0; j < i->second.size(); j++) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY); - std::string loc = safe_locale_to_utf8(i->second.at(j)); + std::string loc = to_utf8(i->second.at(j)); iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(static_cast(32), loc.size()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); @@ -134,7 +164,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr if (i->first == strTags[j].field && !(i->second.empty())) { IptcDataSet * ds = iptc_dataset_new (); iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, strTags[j].tag); - std::string loc = safe_locale_to_utf8(i->second.at(0)); + std::string loc = to_utf8(i->second.at(0)); iptc_dataset_set_data (ds, (unsigned char*)loc.c_str(), min(strTags[j].size, loc.size()), IPTC_DONT_VALIDATE); iptc_data_add_dataset (iptc, ds); iptc_dataset_unref (ds); @@ -177,7 +207,7 @@ void png_flush(png_struct_def *png_ptr); int ImageIO::getPNGSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, IIOSampleArrangement &sArrangement) { - FILE *file = safe_g_fopen (fname, "rb"); + FILE *file = g_fopen (fname.c_str (), "rb"); if (!file) { return IMIO_CANNOTREADFILE; @@ -251,7 +281,7 @@ int ImageIO::getPNGSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat, int ImageIO::loadPNG (Glib::ustring fname) { - FILE *file = safe_g_fopen (fname, "rb"); + FILE *file = g_fopen (fname.c_str (), "rb"); if (!file) { return IMIO_CANNOTREADFILE; @@ -500,7 +530,7 @@ int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize) int ImageIO::loadJPEG (Glib::ustring fname) { - FILE *file = safe_g_fopen(fname, "rb"); + FILE *file = g_fopen(fname.c_str (), "rb"); if (!file) { return IMIO_CANNOTREADFILE; @@ -888,7 +918,7 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) { - FILE *file = safe_g_fopen_WriteBinLock (fname); + FILE *file = g_fopen_withBinaryAndLock (fname); if (!file) { return IMIO_CANNOTWRITEFILE; @@ -982,7 +1012,7 @@ int ImageIO::savePNG (Glib::ustring fname, int compression, volatile int bps) int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) { - FILE *file = safe_g_fopen_WriteBinLock (fname); + FILE *file = g_fopen_withBinaryAndLock (fname); if (!file) { return IMIO_CANNOTWRITEFILE; @@ -1011,7 +1041,7 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) */ jpeg_destroy_compress(&cinfo); fclose(file); - safe_g_remove(fname); + g_remove (fname.c_str()); return IMIO_CANNOTWRITEFILE; } @@ -1130,7 +1160,7 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) delete [] row; jpeg_destroy_compress(&cinfo); fclose(file); - safe_g_remove(fname); + g_remove (fname.c_str()); return IMIO_CANNOTWRITEFILE; } @@ -1142,7 +1172,7 @@ int ImageIO::saveJPEG (Glib::ustring fname, int quality, int subSamp) jpeg_destroy_compress (&cinfo); delete [] row; fclose (file); - safe_g_remove(fname); + g_remove (fname.c_str()); return IMIO_CANNOTWRITEFILE; } @@ -1183,7 +1213,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) // TODO the following needs to be looked into - do we really need two ways to write a Tiff file ? if (exifRoot && uncompressed) { - FILE *file = safe_g_fopen_WriteBinLock (fname); + FILE *file = g_fopen_withBinaryAndLock (fname); if (!file) { delete [] linebuffer; @@ -1370,7 +1400,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) if(writeOk) { return IMIO_SUCCESS; } else { - safe_g_remove(fname); + g_remove (fname.c_str()); return IMIO_CANNOTWRITEFILE; } } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index ee75e831a..2f14c1ded 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -242,7 +242,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } - if ((todo & (M_RETINEX|M_INIT)) && params.retinex.enabled) { + if ((todo & (M_RETINEX | M_INIT)) && params.retinex.enabled) { bool dehacontlutili = false; bool mapcontlutili = false; bool useHsl = false; @@ -388,8 +388,16 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false); - readyphase++; + if ((todo & (M_TRANSFORM)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) { + const int W = oprevi->getWidth(); + const int H = oprevi->getHeight(); + LabImage labcbdl(W, H); + ipf.rgb2lab(*oprevi, labcbdl, params.icm.working); + ipf.dirpyrequalizer (&labcbdl, scale); + ipf.lab2rgb(labcbdl, *oprevi, params.icm.working); + } + readyphase++; progress ("Preparing shadow/highlight map...", 100 * readyphase / numofphases); if ((todo & M_BLURMAP) && params.sh.enabled) { @@ -407,6 +415,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) shmap->update (oprevi, shradius, ipf.lumimul, params.sh.hq, scale); } + + readyphase++; if (todo & M_AUTOEXP) { @@ -439,6 +449,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) CurveFactory::RGBCurve (params.rgbCurves.gcurve, gCurve, scale == 1 ? 1 : 1); CurveFactory::RGBCurve (params.rgbCurves.bcurve, bCurve, scale == 1 ? 1 : 1); + TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); double wp[3][3] = { {wprof[0][0], wprof[0][1], wprof[0][2]}, @@ -656,15 +667,15 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } */ - //if (scale==1) { - if((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { - progress ("Pyramid wavelet...", 100 * readyphase / numofphases); - ipf.dirpyrequalizer (nprevl, scale); - //ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale); - readyphase++; + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if(((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) ) { + progress ("Pyramid wavelet...", 100 * readyphase / numofphases); + ipf.dirpyrequalizer (nprevl, scale); + //ipf.Lanczoslab (ip_wavelet(LabImage * lab, LabImage * dst, const procparams::EqualizerParams & eqparams), nprevl, 1.f/scale); + readyphase++; + } } - //} wavcontlutili = false; //CurveFactory::curveWavContL ( wavcontlutili,params.wavelet.lcurve, wavclCurve, LUTu & histogramwavcl, LUTu & outBeforeWavCLurveHistogram,int skip); @@ -782,6 +793,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } } } + // Update the monitor color transform if necessary if (todo & M_MONITOR) { ipf.updateColorProfiles(params.icm, monitorProfile, monitorIntent); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 468abbe13..339f5e07a 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -52,45 +52,7 @@ namespace rtengine using namespace procparams; -#undef ABS -#undef CLIPS -#undef CLIPC - -#define ABS(a) ((a)<0?-(a):(a)) -#define CLIPS(a) ((a)>-32768?((a)<32767?(a):32767):-32768) -#define CLIPC(a) ((a)>-32000?((a)<32000?(a):32000):-32000) -#define CLIP2(a) ((a)0.0?((a)<65535.5?(a):65535.5):0.0) - - extern const Settings* settings; -LUTf ImProcFunctions::cachef; -LUTf ImProcFunctions::gamma2curve; -void ImProcFunctions::initCache () -{ - - const int maxindex = 65536; - cachef(maxindex, 0/*LUT_CLIP_BELOW*/); - - gamma2curve(maxindex, 0); - - for (int i = 0; i < maxindex; i++) { - if (i > Color::eps_max) { - cachef[i] = 327.68 * ( exp(1.0 / 3.0 * log((double)i / MAXVALD) )); - } else { - cachef[i] = 327.68 * ((Color::kappa * i / MAXVALD + 16.0) / 116.0); - } - } - - for (int i = 0; i < maxindex; i++) { - gamma2curve[i] = (CurveFactory::gamma2(i / 65535.0) * 65535.0); - } -} - -void ImProcFunctions::cleanupCache () -{ - -} ImProcFunctions::~ImProcFunctions () { @@ -3421,10 +3383,22 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer fGammaLUTf[i] = CurveFactory::gamma2 (float(i) / 65535.f) * 65535.f; } - if (hasColorToning || blackwhite) { + if (hasColorToning || blackwhite || (params->dirpyrequalizer.cbdlMethod == "bef" && params->dirpyrequalizer.enabled)) { tmpImage = new Imagefloat(working->width, working->height); } + int W = working->width; + int H = working->height; + + + + + + + + + + #define TS 112 #ifdef _OPENMP @@ -3806,9 +3780,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer y = toxyz[1][0] * r1 + toxyz[1][1] * g1 + toxyz[1][2] * b1; z = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1; - fx = (x < 65535.0f ? cachef[std::max(x, 0.f)] : (327.68f * float(exp(log(x / MAXVALF) / 3.0f )))); - fy = (y < 65535.0f ? cachef[std::max(y, 0.f)] : (327.68f * float(exp(log(y / MAXVALF) / 3.0f )))); - fz = (z < 65535.0f ? cachef[std::max(z, 0.f)] : (327.68f * float(exp(log(z / MAXVALF) / 3.0f )))); + fx = (x < 65535.0f ? Color::cachef[std::max(x, 0.f)] : 327.68f * std::cbrt(x / MAXVALF)); + fy = (y < 65535.0f ? Color::cachef[std::max(y, 0.f)] : 327.68f * std::cbrt(y / MAXVALF)); + fz = (z < 65535.0f ? Color::cachef[std::max(z, 0.f)] : 327.68f * std::cbrt(z / MAXVALF)); L_1 = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; a_1 = (500.0f * (fx - fy) ); @@ -3836,7 +3810,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer // Luminosity after // only Luminance in Lab yy = toxyz[1][0] * r2 + toxyz[1][1] * g2 + toxyz[1][2] * b2; - fyy = (yy < 65535.0f ? cachef[std::max(yy, 0.f)] : (327.68f * float(exp(log(yy / MAXVALF) / 3.0f )))); + fyy = (yy < 65535.0f ? Color::cachef[std::max(yy, 0.f)] : 327.68f * std::cbrt(yy / MAXVALF)); L_2 = (116.0f * fyy - 5242.88f); //gamut control @@ -4217,48 +4191,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } } - //Film Simulations - if ( colorLUT ) { - for (int i = istart, ti = 0; i < tH; i++, ti++) { - for (int j = jstart, tj = 0; j < tW; j++, tj++) { - float &sourceR = rtemp[ti * TS + tj]; - float &sourceG = gtemp[ti * TS + tj]; - float &sourceB = btemp[ti * TS + tj]; - - if (!clutAndWorkingProfilesAreSame) { - //convert from working to clut profile - float x, y, z; - Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, work2xyz ); - Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2clut ); - } - - //appply gamma sRGB (default RT) - sourceR = CLIP( Color::gamma_srgb( sourceR ) ); - sourceG = CLIP( Color::gamma_srgb( sourceG ) ); - sourceB = CLIP( Color::gamma_srgb( sourceB ) ); - - float r, g, b; - colorLUT->getRGB( sourceR, sourceG, sourceB, r, g, b ); - // apply strength - sourceR = r * filmSimCorrectedStrength + sourceR * filmSimSourceStrength; - sourceG = g * filmSimCorrectedStrength + sourceG * filmSimSourceStrength; - sourceB = b * filmSimCorrectedStrength + sourceB * filmSimSourceStrength; - // apply inverse gamma sRGB - sourceR = Color::igamma_srgb( sourceR ); - sourceG = Color::igamma_srgb( sourceG ); - sourceB = Color::igamma_srgb( sourceB ); - - if (!clutAndWorkingProfilesAreSame) { - //convert from clut to working profile - float x, y, z; - Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, clut2xyz ); - Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2work ); - } - - } - } - } - //black and white if(blackwhite) { if (hasToneCurvebw1) { @@ -4405,6 +4337,50 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } } + + //Film Simulations + if ( colorLUT ) { + for (int i = istart, ti = 0; i < tH; i++, ti++) { + for (int j = jstart, tj = 0; j < tW; j++, tj++) { + float &sourceR = rtemp[ti * TS + tj]; + float &sourceG = gtemp[ti * TS + tj]; + float &sourceB = btemp[ti * TS + tj]; + + if (!clutAndWorkingProfilesAreSame) { + //convert from working to clut profile + float x, y, z; + Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, work2xyz ); + Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2clut ); + } + + //appply gamma sRGB (default RT) + sourceR = CLIP( Color::gamma_srgb( sourceR ) ); + sourceG = CLIP( Color::gamma_srgb( sourceG ) ); + sourceB = CLIP( Color::gamma_srgb( sourceB ) ); + + float r, g, b; + colorLUT->getRGB( sourceR, sourceG, sourceB, r, g, b ); + // apply strength + sourceR = r * filmSimCorrectedStrength + sourceR * filmSimSourceStrength; + sourceG = g * filmSimCorrectedStrength + sourceG * filmSimSourceStrength; + sourceB = b * filmSimCorrectedStrength + sourceB * filmSimSourceStrength; + // apply inverse gamma sRGB + sourceR = Color::igamma_srgb( sourceR ); + sourceG = Color::igamma_srgb( sourceG ); + sourceB = Color::igamma_srgb( sourceB ); + + if (!clutAndWorkingProfilesAreSame) { + //convert from clut to working profile + float x, y, z; + Color::rgbxyz( sourceR, sourceG, sourceB, x, y, z, clut2xyz ); + Color::xyz2rgb( x, y, z, sourceR, sourceG, sourceB, xyz2work ); + } + + } + } + } + + if(!blackwhite) { // ready, fill lab for (int i = istart, ti = 0; i < tH; i++, ti++) { @@ -4429,9 +4405,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float fx, fy, fz; - fx = (x < 65535.0f ? cachef[std::max(x, 0.f)] : (327.68f * float(exp(log(x / MAXVALF) / 3.0f )))); - fy = (y < 65535.0f ? cachef[std::max(y, 0.f)] : (327.68f * float(exp(log(y / MAXVALF) / 3.0f )))); - fz = (z < 65535.0f ? cachef[std::max(z, 0.f)] : (327.68f * float(exp(log(z / MAXVALF) / 3.0f )))); + fx = (x < 65535.0f ? Color::cachef[std::max(x, 0.f)] : 327.68f * std::cbrt(x / MAXVALF)); + fy = (y < 65535.0f ? Color::cachef[std::max(y, 0.f)] : 327.68f * std::cbrt(y / MAXVALF)); + fz = (z < 65535.0f ? Color::cachef[std::max(z, 0.f)] : 327.68f * std::cbrt(z / MAXVALF)); lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; lab->a[i][j] = (500.0f * (fx - fy) ); @@ -4879,9 +4855,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float fx, fy, fz; - fx = (x < 65535.0f ? cachef[std::max(x, 0.f)] : (327.68f * float(exp(log(x / MAXVALF) / 3.0f )))); - fy = (y < 65535.0f ? cachef[std::max(y, 0.f)] : (327.68f * float(exp(log(y / MAXVALF) / 3.0f )))); - fz = (z < 65535.0f ? cachef[std::max(z, 0.f)] : (327.68f * float(exp(log(z / MAXVALF) / 3.0f )))); + fx = (x < 65535.0f ? Color::cachef[std::max(x, 0.f)] : 327.68f * std::cbrt(x / MAXVALF)); + fy = (y < 65535.0f ? Color::cachef[std::max(y, 0.f)] : 327.68f * std::cbrt(y / MAXVALF)); + fz = (z < 65535.0f ? Color::cachef[std::max(z, 0.f)] : 327.68f * std::cbrt(z / MAXVALF)); lab->L[i][j] = (116.0f * fy - 5242.88f); //5242.88=16.0*327.68; lab->a[i][j] = (500.0f * (fx - fy) ); @@ -6483,7 +6459,6 @@ void ImProcFunctions::badpixlab(LabImage* lab, double rad, int thr, int mode, fl void ImProcFunctions::dirpyrequalizer (LabImage* lab, int scale) { - if (params->dirpyrequalizer.enabled && lab->W >= 8 && lab->H >= 8) { float b_l = static_cast(params->dirpyrequalizer.hueskin.value[0]) / 100.0f; float t_l = static_cast(params->dirpyrequalizer.hueskin.value[1]) / 100.0f; @@ -7091,8 +7066,79 @@ double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_si } } +void ImProcFunctions::rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace) +{ + TMatrix wprof = iccStore->workingSpaceMatrix( workingSpace ); + const float wp[3][3] = { + {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, + {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, + {static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])} + }; + + const int W = src.getWidth(); + const int H = src.getHeight(); + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = 0; i < H; i++) { + for(int j = 0; j < W; j++) { + float X, Y, Z; + Color::rgbxyz(src.r(i, j), src.g(i, j), src.b(i, j), X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, dst.L[i][j], dst.a[i][j], dst.b[i][j]); + } + } +} + +SSEFUNCTION void ImProcFunctions::lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace) +{ + TMatrix wiprof = iccStore->workingSpaceInverseMatrix( workingSpace ); + const float wip[3][3] = { + {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, + {static_cast(wiprof[1][0]), static_cast(wiprof[1][1]), static_cast(wiprof[1][2])}, + {static_cast(wiprof[2][0]), static_cast(wiprof[2][1]), static_cast(wiprof[2][2])} + }; + + const int W = dst.getWidth(); + const int H = dst.getHeight(); +#ifdef __SSE2__ + vfloat wipv[3][3]; + + for(int i = 0; i < 3; i++) { + for(int j = 0; j < 3; j++) { + wipv[i][j] = F2V(wiprof[i][j]); + } + } +#endif + +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = 0; i < H; i++) { + int j = 0; +#ifdef __SSE2__ + for(; j < W - 3; j += 4) { + vfloat X, Y, Z; + vfloat R,G,B; + Color::Lab2XYZ(LVFU(src.L[i][j]), LVFU(src.a[i][j]), LVFU(src.b[i][j]), X, Y, Z); + Color::xyz2rgb(X, Y, Z, R, G, B, wipv); + STVFU(dst.r(i, j), R); + STVFU(dst.g(i, j), G); + STVFU(dst.b(i, j), B); + } + +#endif + for(; j < W; j++) { + float X, Y, Z; + Color::Lab2XYZ(src.L[i][j], src.a[i][j], src.b[i][j], X, Y, Z); + Color::xyz2rgb(X, Y, Z, dst.r(i, j), dst.g(i, j), dst.b(i, j), wip); + } + } +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } -#undef PIX_SORT -#undef med3x3 diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 996f91c58..90a046149 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -57,7 +57,6 @@ using namespace procparams; class ImProcFunctions { - static LUTf gamma2curve; cmsHTRANSFORM monitorTransform; cmsHTRANSFORM lab2outputTransform; @@ -201,7 +200,6 @@ class ImProcFunctions public: - static LUTf cachef; double lumimul[3]; // float chau; // float chred; @@ -221,8 +219,6 @@ public: // float maxblueresid;//used by noise_residual // int comptlevel; - static void initCache (); - static void cleanupCache (); ImProcFunctions (const ProcParams* iparams, bool imultiThread = true) : monitorTransform(NULL), lab2outputTransform(NULL), output2monitorTransform(NULL), params(iparams), scale(1), multiThread(imultiThread) {} @@ -286,6 +282,7 @@ public: void dirpyrdenoise (LabImage* src);//Emil's pyramid denoise void dirpyrequalizer (LabImage* lab, int scale);//Emil's wavelet + void EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params& cp, int W_L, int H_L, float max0, float min0); float *CompressDR(float *Source, int skip, struct cont_params &cp, int W_L, int H_L, float Compression, float DetailBoost, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx, float *Compressed); void ContrastResid(float * WavCoeffs_L0, unsigned int Iterates, int skip, struct cont_params &cp, int W_L, int H_L, float max0, float min0, float ave, float ah, float bh, float al, float bl, float factorx); @@ -383,6 +380,8 @@ public: static void getAutoExp (LUTu & histogram, int histcompr, double defgain, double clip, double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh); static double getAutoDistor (const Glib::ustring& fname, int thumb_size); double getTransformAutoFill (int oW, int oH, const LCPMapper *pLCPMap = NULL); + void rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace); + void lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace); }; } #endif diff --git a/rtengine/init.cc b/rtengine/init.cc index 9fa5c48ee..d2509b620 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -39,11 +39,9 @@ MyMutex* lcmsMutex = NULL; int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir) { - settings = s; iccStore->init (s->iccDirectory, baseDir + "/iccprofiles"); iccStore->findDefaultMonitorProfile(); - dcpStore->init (baseDir + "/dcpprofiles"); CameraConstantsStore::getInstance ()->init (baseDir, userSettingsDir); @@ -52,8 +50,6 @@ int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDi Color::init (); PerceptualToneCurve::init (); RawImageSource::init (); - ImProcFunctions::initCache (); - Thumbnail::initGamma (); delete lcmsMutex; lcmsMutex = new MyMutex; dfm.init( s->darkFramesPath ); @@ -66,8 +62,6 @@ void cleanup () ProcParams::cleanup (); Color::cleanup (); - ImProcFunctions::cleanupCache (); - Thumbnail::cleanupGamma (); RawImageSource::cleanup (); } diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 89deac08f..4510044aa 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -117,9 +117,9 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) /* copy RGB */ //int R1=((int)gamma2curve[(R)]) - data[ix++] = ((int)gamma2curve[CLIP(R)]) >> 8; - data[ix++] = ((int)gamma2curve[CLIP(G)]) >> 8; - data[ix++] = ((int)gamma2curve[CLIP(B)]) >> 8; + data[ix++] = ((int)Color::gamma2curve[CLIP(R)]) >> 8; + data[ix++] = ((int)Color::gamma2curve[CLIP(G)]) >> 8; + data[ix++] = ((int)Color::gamma2curve[CLIP(B)]) >> 8; } } } @@ -229,9 +229,9 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Color::xyz2rgb(x_, y_, z_, R, G, B, rgb_xyz); - image->data[ix++] = (int)gamma2curve[CLIP(R)] >> 8; - image->data[ix++] = (int)gamma2curve[CLIP(G)] >> 8; - image->data[ix++] = (int)gamma2curve[CLIP(B)] >> 8; + image->data[ix++] = (int)Color::gamma2curve[CLIP(R)] >> 8; + image->data[ix++] = (int)Color::gamma2curve[CLIP(G)] >> 8; + image->data[ix++] = (int)Color::gamma2curve[CLIP(B)] >> 8; } } } @@ -331,9 +331,9 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int Color::xyz2srgb(x_, y_, z_, R, G, B); - image->r(i - cy, j - cx) = (int)gamma2curve[CLIP(R)]; - image->g(i - cy, j - cx) = (int)gamma2curve[CLIP(G)]; - image->b(i - cy, j - cx) = (int)gamma2curve[CLIP(B)]; + image->r(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(R)]; + image->g(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(G)]; + image->b(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(B)]; } } } @@ -601,9 +601,9 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int Color::xyz2srgb(x_, y_, z_, R, G, B); - image->r(i - cy, j - cx) = (int)gamma2curve[CLIP(R)]; - image->g(i - cy, j - cx) = (int)gamma2curve[CLIP(G)]; - image->b(i - cy, j - cx) = (int)gamma2curve[CLIP(B)]; + image->r(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(R)]; + image->g(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(G)]; + image->b(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(B)]; } } } diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc index 8dc0ced62..60ac6df0a 100644 --- a/rtengine/ipretinex.cc +++ b/rtengine/ipretinex.cc @@ -45,7 +45,7 @@ #include "rawimagesource.h" #include "improcfun.h" #include "opthelper.h" -#define BENCHMARK +//#define BENCHMARK #include "StopWatch.h" #define MAX_RETINEX_SCALES 8 diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 903e54a0a..1ed601301 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -19,7 +19,6 @@ #include #include "lcp.h" -#include "safegtk.h" #include "iccmatrices.h" #include "iccstore.h" #include "rawimagesource.h" @@ -303,7 +302,7 @@ LCPProfile::LCPProfile(Glib::ustring fname) persModelCount = 0; *inInvalidTag = 0; - FILE *pFile = safe_g_fopen(fname, "rb"); + FILE *pFile = g_fopen(fname.c_str (), "rb"); bool done; @@ -807,7 +806,7 @@ LCPProfile* LCPStore::getProfile (Glib::ustring filename) bool LCPStore::isValidLCPFileName(Glib::ustring filename) const { - if (!safe_file_test (filename, Glib::FILE_TEST_EXISTS) || safe_file_test (filename, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (filename, Glib::FILE_TEST_EXISTS) || Glib::file_test (filename, Glib::FILE_TEST_IS_DIR)) { return false; } @@ -828,7 +827,7 @@ Glib::ustring LCPStore::getDefaultCommonDirectory() const WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); Glib::ustring fullDir = Glib::ustring(pathA) + Glib::ustring("\\Adobe\\CameraRaw\\LensProfiles\\1.0"); - if (safe_file_test(fullDir, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (fullDir, Glib::FILE_TEST_IS_DIR)) { dir = fullDir; } } diff --git a/rtengine/myfile.cc b/rtengine/myfile.cc index 1ff457234..bcc2a7db7 100644 --- a/rtengine/myfile.cc +++ b/rtengine/myfile.cc @@ -19,7 +19,6 @@ #include "myfile.h" #include #include -#include "safegtk.h" #ifdef BZIP_SUPPORT #include #endif @@ -58,6 +57,7 @@ int munmap(void *start, size_t length) #else // WIN32 +#include #include #include @@ -68,7 +68,25 @@ int munmap(void *start, size_t length) IMFILE* fopen (const char* fname) { - int fd = safe_open_ReadOnly(fname); + int fd = -1; + +#ifdef WIN32 + + { + // First convert UTF8 to UTF16, then use Windows function to open the file and convert back to file descriptor. + std::unique_ptr wfname (reinterpret_cast(g_utf8_to_utf16 (fname, -1, NULL, NULL, NULL)), g_free); + + HANDLE hFile = CreateFileW (wfname.get (), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + fd = _open_osfhandle((intptr_t)hFile, 0); + } + } + +#else + + fd = ::g_open (fname, O_RDONLY); + +#endif if ( fd < 0 ) { return 0; @@ -78,7 +96,7 @@ IMFILE* fopen (const char* fname) if ( fstat(fd, &stat_buffer) < 0 ) { printf("no stat\n"); - close(fd); + close (fd); return 0; } diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index 86333bc3e..9de5c81cb 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -23,8 +23,6 @@ #include "iimage.h" #include "rtthumbnail.h" #include "rawimagesource.h" -#include "StopWatch.h" -#include "utils.h" using namespace rtengine; using namespace procparams; @@ -135,9 +133,7 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext rawImage.getImage (wb, TR_NONE, image, pp, params.toneCurve, params.icm, params.raw); output = new Image8(fw, fh); rawImage.convertColorSpace(image, params.icm, wb); - StopWatch Stop1("inspector loop"); #pragma omp parallel for schedule(dynamic, 10) - for (int i = 0; i < fh; ++i) for (int j = 0; j < fw; ++j) { image->r(i, j) = Color::gamma2curve[image->r(i, j)]; @@ -145,7 +141,6 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext image->b(i, j) = Color::gamma2curve[image->b(i, j)]; } - Stop1.stop(); image->resizeImgTo(fw, fh, TI_Nearest, output); data = output->getData(); diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 558f509c2..3d4f90af1 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -466,7 +466,9 @@ enum ProcEvent { EvmapMethod = 436, EvRetinexmapcurve = 437, EvviewMethod = 438, + EvcbdlMethod = 439, NUMOFEVENTS + }; } #endif diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index f79f51c91..9c4ddbd58 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -16,11 +16,9 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -//#include +#include #include "procparams.h" #include "rt_math.h" -#include "safegtk.h" -#include "safekeyfile.h" #include "dcp.h" #include "../rtgui/multilangmgr.h" #include "../rtgui/version.h" @@ -890,6 +888,7 @@ void RAWParams::setDefaults() ff_clipControl = 0; cared = 0; cablue = 0; + caautostrength = 6; ca_autocorrect = false; hotPixelFilter = false; deadPixelFilter = false; @@ -1219,6 +1218,8 @@ void ProcParams::setDefaults () dirpyrequalizer.enabled = false; dirpyrequalizer.gamutlab = false; + dirpyrequalizer.cbdlMethod = "bef"; + for(int i = 0; i < 6; i ++) { dirpyrequalizer.mult[i] = 1.0; @@ -1303,11 +1304,15 @@ static Glib::ustring relativePathIfInside(Glib::ustring procparams_fname, bool f int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsolute, ParamsEdited* pedited) { - if (!fname.length() && !fname2.length()) { + if (fname.empty () && fname2.empty ()) { return 0; } - SafeKeyFile keyFile; + Glib::ustring sPParams; + + try { + + Glib::KeyFile keyFile; keyFile.set_string ("Version", "AppVersion", APPVERSION); keyFile.set_integer ("Version", "Version", PPVERSION); @@ -3028,6 +3033,10 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_boolean ("Directional Pyramid Equalizer", "Gamutlab", dirpyrequalizer.gamutlab); } + if (!pedited || pedited->dirpyrequalizer.cbdlMethod) { + keyFile.set_string ("Directional Pyramid Equalizer", "cbdlMethod", dirpyrequalizer.cbdlMethod); + } + for(int i = 0; i < 6; i++) { std::stringstream ss; ss << "Mult" << i; @@ -3248,6 +3257,10 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol keyFile.set_boolean ("RAW", "CA", raw.ca_autocorrect ); } + if (!pedited || pedited->raw.caAutoStrength) { + keyFile.set_double ("RAW", "CAAutoStrength", raw.caautostrength ); + } + if (!pedited || pedited->raw.caRed) { keyFile.set_double ("RAW", "CARed", raw.cared ); } @@ -3363,12 +3376,18 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol } } - Glib::ustring sPParams = keyFile.to_data(); + sPParams = keyFile.to_data(); + + } catch(Glib::KeyFileError&) {} + + if (sPParams.empty ()) { + return 1; + } int error1, error2; - error1 = write (fname , sPParams); + error1 = write (fname, sPParams); - if (fname2.length()) { + if (!fname2.empty ()) { error2 = write (fname2, sPParams); // If at least one file has been saved, it's a success @@ -3385,7 +3404,7 @@ int ProcParams::write (Glib::ustring &fname, Glib::ustring &content) const if (fname.length()) { FILE *f; - f = safe_g_fopen (fname, "wt"); + f = g_fopen (fname.c_str (), "wt"); if (f == NULL) { error = 1; @@ -3406,15 +3425,15 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) return 1; } - SafeKeyFile keyFile; + Glib::KeyFile keyFile; try { - //setDefaults (); + if (pedited) { pedited->set(false); } - FILE* f = safe_g_fopen (fname, "rt"); + FILE* f = g_fopen (fname.c_str (), "rt"); if (!f) { return 1; @@ -3450,8 +3469,6 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } -//printf("ProcParams::load called ppVersion=%i\n",ppVersion); - if (keyFile.has_group ("General")) { if (keyFile.has_key ("General", "Rank")) { rank = keyFile.get_integer ("General", "Rank"); @@ -6610,6 +6627,16 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + + if (keyFile.has_key ("Directional Pyramid Equalizer", "cbdlMethod")) { + dirpyrequalizer.cbdlMethod = keyFile.get_string ("Directional Pyramid Equalizer", "cbdlMethod"); + + if (pedited) { + pedited->dirpyrequalizer.cbdlMethod = true; + } + } + + // if (keyFile.has_key ("Directional Pyramid Equalizer", "Algorithm")) { dirpyrequalizer.algo = keyFile.get_string ("Directional Pyramid Equalizer", "Algorithm"); if (pedited) pedited->dirpyrequalizer.algo = true; } if (keyFile.has_key ("Directional Pyramid Equalizer", "Hueskin")) { Glib::ArrayHandle thresh = keyFile.get_integer_list ("Directional Pyramid Equalizer", "Hueskin"); @@ -7058,6 +7085,14 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } + if (keyFile.has_key ("RAW", "CAAutoStrength")) { + raw.caautostrength = keyFile.get_double ("RAW", "CAAutoStrength" ); + + if (pedited) { + pedited->raw.caAutoStrength = true; + } + } + if (keyFile.has_key ("RAW", "CARed")) { raw.cared = keyFile.get_double ("RAW", "CARed" ); @@ -7427,9 +7462,11 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) return 0; } catch (const Glib::Error& e) { printf ("-->%s\n", e.what().c_str()); + setDefaults (); return 1; } catch (...) { printf ("-->unknown exception!\n"); + setDefaults (); return 1; } @@ -7777,6 +7814,7 @@ bool ProcParams::operator== (const ProcParams& other) && raw.expos == other.raw.expos && raw.preser == other.raw.preser && raw.ca_autocorrect == other.raw.ca_autocorrect + && raw.caautostrength == other.raw.caautostrength && raw.cared == other.raw.cared && raw.cablue == other.raw.cablue && raw.hotPixelFilter == other.raw.hotPixelFilter @@ -7880,6 +7918,7 @@ bool ProcParams::operator== (const ProcParams& other) // && dirpyrequalizer.algo == other.dirpyrequalizer.algo && dirpyrequalizer.hueskin == other.dirpyrequalizer.hueskin && dirpyrequalizer.threshold == other.dirpyrequalizer.threshold + && dirpyrequalizer.cbdlMethod == other.dirpyrequalizer.cbdlMethod && dirpyrequalizer.skinprotect == other.dirpyrequalizer.skinprotect && hsvequalizer.hcurve == other.hsvequalizer.hcurve && hsvequalizer.scurve == other.hsvequalizer.scurve diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 47b8f1cf1..7946ce4d9 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1106,7 +1106,7 @@ public: double skinprotect; Threshold hueskin; //Glib::ustring algo; - + Glib::ustring cbdlMethod; DirPyrEqualizerParams() : hueskin(20, 80, 2000, 1200, false) {}; }; @@ -1218,6 +1218,7 @@ public: int ff_clipControl; bool ca_autocorrect; + double caautostrength; double cared; double cablue; diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 040d0276b..3f4b2ac3f 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -13,7 +13,6 @@ #else #include #endif -#include "safegtk.h" namespace rtengine { diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index d1d4da54f..75aab5951 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1422,6 +1422,7 @@ SSEFUNCTION int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thres } #else + // 25 fabs function calls and 25 float additions without SSE for (int mm = rr - 2; mm <= rr + 2; mm++) { for (int nn = cc - 2; nn <= cc + 2; nn++) { @@ -1865,7 +1866,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le plistener->setProgress (0.0); } - CA_correct_RT(raw.cared, raw.cablue); + CA_correct_RT(raw.cared, raw.cablue, 10.0 - raw.caautostrength); } if ( raw.expos != 1 ) { @@ -4209,14 +4210,14 @@ void RawImageSource::HLRecovery_CIELab (float* rin, float* gin, float* bin, floa float go = min(g, maxval); float bo = min(b, maxval); float yy = xyz_cam[1][0] * r + xyz_cam[1][1] * g + xyz_cam[1][2] * b; - float fy = (yy < 65535.0 ? ImProcFunctions::cachef[yy] / 327.68 : (exp(log(yy / MAXVALD) / 3.0 ))); + float fy = (yy < 65535.0 ? Color::cachef[yy] / 327.68 : std::cbrt(yy / MAXVALD)); // compute LCH decompostion of the clipped pixel (only color information, thus C and H will be used) float x = xyz_cam[0][0] * ro + xyz_cam[0][1] * go + xyz_cam[0][2] * bo; float y = xyz_cam[1][0] * ro + xyz_cam[1][1] * go + xyz_cam[1][2] * bo; float z = xyz_cam[2][0] * ro + xyz_cam[2][1] * go + xyz_cam[2][2] * bo; - x = (x < 65535.0 ? ImProcFunctions::cachef[x] / 327.68 : (exp(log(x / MAXVALD) / 3.0 ))); - y = (y < 65535.0 ? ImProcFunctions::cachef[y] / 327.68 : (exp(log(y / MAXVALD) / 3.0 ))); - z = (z < 65535.0 ? ImProcFunctions::cachef[z] / 327.68 : (exp(log(z / MAXVALD) / 3.0 ))); + x = (x < 65535.0 ? Color::cachef[x] / 327.68 : std::cbrt(x / MAXVALD)); + y = (y < 65535.0 ? Color::cachef[y] / 327.68 : std::cbrt(y / MAXVALD)); + z = (z < 65535.0 ? Color::cachef[z] / 327.68 : std::cbrt(z / MAXVALD)); // convert back to rgb double fz = fy - y + z; double fx = fy + x - y; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index bef4ad4e2..3cb345536 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -215,8 +215,7 @@ protected: inline void interpolate_row_rb (float* ar, float* ab, float* pg, float* cg, float* ng, int i); inline void interpolate_row_rb_mul_pp (float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip); - int LinEqSolve( int nDim, double* pfMatr, double* pfVect, double* pfSolution);//Emil's CA auto correction - void CA_correct_RT (double cared, double cablue); + void CA_correct_RT (const double cared, const double cablue, const double caautostrength); void ddct8x8s(int isgn, float a[8][8]); void processRawWhitepoint (float expos, float preser); // exposure before interpolation diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 6a2925be9..1bcaf3fa3 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -119,8 +119,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = { ALLNORAW, // EvDPDNLuma, ALLNORAW, // EvDPDNChroma, ALLNORAW, // EvDPDNGamma, - DIRPYREQUALIZER, // EvDirPyrEqualizer, - DIRPYREQUALIZER, // EvDirPyrEqlEnabled, + ALLNORAW, // EvDirPyrEqualizer, + ALLNORAW, // EvDirPyrEqlEnabled, LUMINANCECURVE, // EvLSaturation, LUMINANCECURVE, // EvLaCurve, LUMINANCECURVE, // EvLbCurve, @@ -200,7 +200,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvLLCCurve LUMINANCECURVE, // EvLLCredsk ALLNORAW, // EvDPDNLdetail - LUMINANCECURVE, // EvCATEnabled + ALLNORAW, // EvCATEnabled LUMINANCECURVE, // EvCATDegree LUMINANCECURVE, // EvCATMethodsur LUMINANCECURVE, // EvCATAdapscen @@ -275,12 +275,12 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, // EvLCLCurve LUMINANCECURVE, // EvLLHCurve LUMINANCECURVE, // EvLHHCurve - DIRPYREQUALIZER, // EvDirPyrEqualizerThreshold + ALLNORAW, // EvDirPyrEqualizerThreshold ALLNORAW, // EvDPDNenhance RGBCURVE, // EvBWMethodalg - DIRPYREQUALIZER, // EvDirPyrEqualizerSkin - DIRPYREQUALIZER, // EvDirPyrEqlgamutlab - DIRPYREQUALIZER, // EvDirPyrEqualizerHueskin + ALLNORAW, // EvDirPyrEqualizerSkin + ALLNORAW, // EvDirPyrEqlgamutlab + ALLNORAW, // EvDirPyrEqualizerHueskin ALLNORAW, // EvDPDNmedian ALLNORAW, // EvDPDNmedmet RGBCURVE, // EvColorToningEnabled @@ -465,6 +465,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { RETINEX, // EvLradius RETINEX, // EvmapMethod DEMOSAIC, // EvRetinexmapcurve - DEMOSAIC // EvviewMethod + DEMOSAIC, // EvviewMethod + ALLNORAW // EvcbdlMethod }; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 1f81012ad..e4729bead 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -33,8 +33,6 @@ #include "stdimagesource.h" #include #include -#include "safekeyfile.h" -#include "safegtk.h" #include "rawimage.h" #include "jpeg.h" #include "../rtgui/ppversion.h" @@ -720,30 +718,6 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati #undef FISGREEN #undef FISBLUE - -unsigned short *Thumbnail::igammatab = 0; -unsigned char *Thumbnail::gammatab = 0; - -void Thumbnail::initGamma () -{ - igammatab = new unsigned short[256]; - gammatab = new unsigned char[65536]; - - for (int i = 0; i < 256; i++) { - igammatab[i] = (unsigned short)(255.0 * pow((double)i / 255.0, Color::sRGBGamma)); - } - - for (int i = 0; i < 65536; i++) { - gammatab[i] = (unsigned char)(255.0 * pow((double)i / 65535.0, 1.f / Color::sRGBGamma)); - } -} - -void Thumbnail::cleanupGamma () -{ - delete [] igammatab; - delete [] gammatab; -} - void Thumbnail::init () { @@ -1456,9 +1430,9 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); image->convertTo(image->b(i, j), b_); - int r = gammatab[min(r_, static_cast(max_)) * scaleForSave >> 13]; - int g = gammatab[min(g_, static_cast(max_)) * scaleForSave >> 13]; - int b = gammatab[min(b_, static_cast(max_)) * scaleForSave >> 13]; + int r = Color::gammatabThumb[min(r_, static_cast(max_)) * scaleForSave >> 13]; + int g = Color::gammatabThumb[min(g_, static_cast(max_)) * scaleForSave >> 13]; + int b = Color::gammatabThumb[min(b_, static_cast(max_)) * scaleForSave >> 13]; tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } } else if (thumbImg->getType() == sImage16) { @@ -1470,9 +1444,9 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); image->convertTo(image->b(i, j), b_); - int r = gammatab[min(r_, static_cast(max_)) * scaleForSave >> 13]; - int g = gammatab[min(g_, static_cast(max_)) * scaleForSave >> 13]; - int b = gammatab[min(b_, static_cast(max_)) * scaleForSave >> 13]; + int r = Color::gammatabThumb[min(r_, static_cast(max_)) * scaleForSave >> 13]; + int g = Color::gammatabThumb[min(g_, static_cast(max_)) * scaleForSave >> 13]; + int b = Color::gammatabThumb[min(b_, static_cast(max_)) * scaleForSave >> 13]; tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } } else if (thumbImg->getType() == sImagefloat) { @@ -1484,9 +1458,9 @@ unsigned char* Thumbnail::getGrayscaleHistEQ (int trim_width) image->convertTo(image->r(i, j), r_); image->convertTo(image->g(i, j), g_); image->convertTo(image->b(i, j), b_); - int r = gammatab[min(r_, static_cast(max_)) * scaleForSave >> 13]; - int g = gammatab[min(g_, static_cast(max_)) * scaleForSave >> 13]; - int b = gammatab[min(b_, static_cast(max_)) * scaleForSave >> 13]; + int r = Color::gammatabThumb[min(r_, static_cast(max_)) * scaleForSave >> 13]; + int g = Color::gammatabThumb[min(g_, static_cast(max_)) * scaleForSave >> 13]; + int b = Color::gammatabThumb[min(b_, static_cast(max_)) * scaleForSave >> 13]; tmpdata[ix++] = (r * 19595 + g * 38469 + b * 7472) >> 16; } } @@ -1653,7 +1627,7 @@ bool Thumbnail::writeImage (const Glib::ustring& fname, int format) Glib::ustring fullFName = fname + ".rtti"; - FILE* f = safe_g_fopen (fullFName, "wb"); + FILE* f = g_fopen (fullFName.c_str (), "wb"); if (!f) { return false; @@ -1692,11 +1666,11 @@ bool Thumbnail::readImage (const Glib::ustring& fname) Glib::ustring fullFName = fname + ".rtti"; - if (!safe_file_test (fullFName, Glib::FILE_TEST_EXISTS)) { + if (!Glib::file_test (fullFName, Glib::FILE_TEST_EXISTS)) { return false; } - FILE* f = safe_g_fopen (fullFName, "rb"); + FILE* f = g_fopen (fullFName.c_str (), "rb"); if (!f) { return false; @@ -1738,12 +1712,14 @@ bool Thumbnail::readImage (const Glib::ustring& fname) bool Thumbnail::readData (const Glib::ustring& fname) { setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - SafeKeyFile keyFile; + Glib::KeyFile keyFile; try { MyMutex::MyLock thmbLock(thumbMutex); - if (!keyFile.load_from_file (fname)) { + try { + keyFile.load_from_file (fname); + } catch (Glib::Error&) { return false; } @@ -1831,16 +1807,38 @@ bool Thumbnail::readData (const Glib::ustring& fname) bool Thumbnail::writeData (const Glib::ustring& fname) { - - SafeKeyFile keyFile; - MyMutex::MyLock thmbLock(thumbMutex); + Glib::ustring keyData; + try { - if( safe_file_test(fname, Glib::FILE_TEST_EXISTS) ) { + + Glib::KeyFile keyFile; + + try { keyFile.load_from_file (fname); - } - } catch (Glib::Error &err) { + } catch (Glib::Error&) {} + + keyFile.set_double ("LiveThumbData", "CamWBRed", camwbRed); + keyFile.set_double ("LiveThumbData", "CamWBGreen", camwbGreen); + keyFile.set_double ("LiveThumbData", "CamWBBlue", camwbBlue); + keyFile.set_double ("LiveThumbData", "RedAWBMul", redAWBMul); + keyFile.set_double ("LiveThumbData", "GreenAWBMul", greenAWBMul); + keyFile.set_double ("LiveThumbData", "BlueAWBMul", blueAWBMul); + keyFile.set_integer ("LiveThumbData", "AEHistCompression", aeHistCompression); + keyFile.set_double ("LiveThumbData", "RedMultiplier", redMultiplier); + keyFile.set_double ("LiveThumbData", "GreenMultiplier", greenMultiplier); + keyFile.set_double ("LiveThumbData", "BlueMultiplier", blueMultiplier); + keyFile.set_double ("LiveThumbData", "Scale", scale); + keyFile.set_double ("LiveThumbData", "DefaultGain", defGain); + keyFile.set_integer ("LiveThumbData", "ScaleForSave", scaleForSave); + keyFile.set_boolean ("LiveThumbData", "GammaCorrected", gammaCorrected); + Glib::ArrayHandle cm ((double*)colorMatrix, 9, Glib::OWNERSHIP_NONE); + keyFile.set_double_list ("LiveThumbData", "ColorMatrix", cm); + + keyData = keyFile.to_data (); + + } catch (Glib::Error& err) { if (options.rtSettings.verbose) { printf("Thumbnail::writeData / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); } @@ -1850,24 +1848,11 @@ bool Thumbnail::writeData (const Glib::ustring& fname) } } - keyFile.set_double ("LiveThumbData", "CamWBRed", camwbRed); - keyFile.set_double ("LiveThumbData", "CamWBGreen", camwbGreen); - keyFile.set_double ("LiveThumbData", "CamWBBlue", camwbBlue); - keyFile.set_double ("LiveThumbData", "RedAWBMul", redAWBMul); - keyFile.set_double ("LiveThumbData", "GreenAWBMul", greenAWBMul); - keyFile.set_double ("LiveThumbData", "BlueAWBMul", blueAWBMul); - keyFile.set_integer ("LiveThumbData", "AEHistCompression", aeHistCompression); - keyFile.set_double ("LiveThumbData", "RedMultiplier", redMultiplier); - keyFile.set_double ("LiveThumbData", "GreenMultiplier", greenMultiplier); - keyFile.set_double ("LiveThumbData", "BlueMultiplier", blueMultiplier); - keyFile.set_double ("LiveThumbData", "Scale", scale); - keyFile.set_double ("LiveThumbData", "DefaultGain", defGain); - keyFile.set_integer ("LiveThumbData", "ScaleForSave", scaleForSave); - keyFile.set_boolean ("LiveThumbData", "GammaCorrected", gammaCorrected); - Glib::ArrayHandle cm ((double*)colorMatrix, 9, Glib::OWNERSHIP_NONE); - keyFile.set_double_list ("LiveThumbData", "ColorMatrix", cm); + if (keyData.empty ()) { + return false; + } - FILE *f = safe_g_fopen (fname, "wt"); + FILE *f = g_fopen (fname.c_str (), "wt"); if (!f) { if (options.rtSettings.verbose) { @@ -1876,7 +1861,7 @@ bool Thumbnail::writeData (const Glib::ustring& fname) return false; } else { - fprintf (f, "%s", keyFile.to_data().c_str()); + fprintf (f, "%s", keyData.c_str ()); fclose (f); } @@ -1886,7 +1871,7 @@ bool Thumbnail::writeData (const Glib::ustring& fname) bool Thumbnail::readEmbProfile (const Glib::ustring& fname) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (!f) { embProfileData = NULL; @@ -1910,7 +1895,7 @@ bool Thumbnail::writeEmbProfile (const Glib::ustring& fname) { if (embProfileData) { - FILE* f = safe_g_fopen(fname, "wb"); + FILE* f = g_fopen(fname.c_str (), "wb"); if (f) { fwrite (embProfileData, 1, embProfileLength, f); @@ -1925,7 +1910,7 @@ bool Thumbnail::writeEmbProfile (const Glib::ustring& fname) bool Thumbnail::readAEHistogram (const Glib::ustring& fname) { - FILE* f = safe_g_fopen (fname, "rb"); + FILE* f = g_fopen (fname.c_str (), "rb"); if (!f) { aeHistogram(0); @@ -1943,7 +1928,7 @@ bool Thumbnail::writeAEHistogram (const Glib::ustring& fname) { if (aeHistogram) { - FILE* f = safe_g_fopen (fname, "wb"); + FILE* f = g_fopen (fname.c_str (), "wb"); if (f) { fwrite (&aeHistogram[0], 1, (65536 >> aeHistCompression)*sizeof(aeHistogram[0]), f); diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index dd9d8e9ca..bc367522d 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -42,9 +42,6 @@ class Thumbnail void transformPixel (int x, int y, int tran, int& tx, int& ty); - static unsigned short *igammatab; - static unsigned char *gammatab; - ImageIO* thumbImg; double camwbRed; double camwbGreen; @@ -72,8 +69,6 @@ public: ~Thumbnail (); Thumbnail (); - static void initGamma (); - static void cleanupGamma (); void init (); IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, std::string camName, diff --git a/rtengine/safegtk.cc b/rtengine/safegtk.cc deleted file mode 100644 index 053507c3e..000000000 --- a/rtengine/safegtk.cc +++ /dev/null @@ -1,437 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * Copyright (c) 2010 Sasha Vasko - * Copyright (c) 2010 Oliver Duis - * - * RawTherapee 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. - * - * RawTherapee 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 RawTherapee. If not, see . - */ - -#include "safegtk.h" -#include "../rtgui/guiutils.h" -#include -#include -#ifdef WIN32 -#include -// for GCC32 -#ifndef _WIN32_IE -#define _WIN32_IE 0x0600 -#endif -#include -#include -#else -#include -#endif -#include "../rtgui/rtimage.h" -#include - - -Glib::RefPtr safe_create_from_file(const Glib::ustring& filename) -{ - Glib::RefPtr res; - Glib::ustring path = RTImage::findIconAbsolutePath(filename); - - if (path.length()) { - try { - res = Gdk::Pixbuf::create_from_file (path); - } catch (Glib::Exception& ex) { - printf ("ERROR: (ustring) File \"%s\" not found.\n", ex.what().c_str()); - } - } - - return res; -} - -Cairo::RefPtr safe_create_from_png(const Glib::ustring& filename) -{ - Cairo::RefPtr res; - Glib::ustring path = RTImage::findIconAbsolutePath(filename); - - if (path.length()) { - // files_test need a std::string which (as stated in its proto) but will only work if - // we use the Glib::ustring filename !? - try { - // create_from_png need a std::string converted from UTF8 with safe_locale_from_utf8 - res = Cairo::ImageSurface::create_from_png (safe_locale_from_utf8(path)); - } catch (...) { - printf("ERROR: (ustring) File \"%s\" not found.\n", path.c_str()); - } - } - - return res; -} - -Glib::RefPtr safe_query_file_info (Glib::RefPtr &file) -{ - Glib::RefPtr info; - - try { - info = file->query_info(); - } catch (...) { } - - return info; -} - -Glib::RefPtr safe_next_file (Glib::RefPtr &dirList) -{ - Glib::RefPtr info; - - bool retry; - Glib::ustring last_error = ""; - - do { - retry = false; - - try { - info = dirList->next_file(); - } catch (Glib::Exception& ex) { - printf ("%s\n", ex.what().c_str()); - // API problem: not possible to differ between error looking at particular entry or - // general error scanning the directory. We do a hack by retrying and see if the - // error changes, if it does we can assume it's about the current filename and we - // should look at the next. More likely if a single file error is that the next - // retry is okay of course. - retry = (ex.what() != last_error); - last_error = ex.what(); - } - } while (retry); - - return info; -} - -# define SAFE_ENUMERATOR_CODE_START(attributes) \ - do{try { if ((dirList = dir->enumerate_children ((attributes)))) \ - for (Glib::RefPtr info = safe_next_file(dirList); info; info = safe_next_file(dirList)) { - -# define SAFE_ENUMERATOR_CODE_END \ - }} catch (Glib::Exception& ex) { printf ("%s\n", ex.what().c_str()); }}while(0) - -/* - * safe_build_file_list can now filter out at the source all files that don't have the extensions specified (if provided) - */ -void safe_build_file_list (Glib::RefPtr &dir, std::vector &names, const Glib::ustring &directory, const std::vector *extensions) -{ - Glib::RefPtr dirList; - - if (dir) { - if (!extensions) { - SAFE_ENUMERATOR_CODE_START("standard::name") - names.push_back (Glib::build_filename (directory, info->get_name())); - SAFE_ENUMERATOR_CODE_END; - } else { - // convert extensions to lowercase in a new vector list - std::vector lcExtensions; - - for (unsigned int i = 0; i < extensions->size(); i++) { - lcExtensions.push_back ((*extensions)[i].lowercase()); - } - - SAFE_ENUMERATOR_CODE_START("standard::name") - // convert the current filename to lowercase in a new ustring - Glib::ustring fname = Glib::ustring(info->get_name()).lowercase(); - - size_t pos = fname.find_last_of('.'); - - if (pos < (fname.length() - 1)) { - // there is an extension to the filename - - Glib::ustring lcFileExt = fname.substr(pos + 1).lowercase(); - - // look out if it has one of the retained extensions - for (size_t i = 0; i < lcExtensions.size(); i++) { - if (lcFileExt == lcExtensions[i]) { - names.push_back (Glib::build_filename (directory, info->get_name())); - break; - } - } - } - - SAFE_ENUMERATOR_CODE_END; - } - } -} - - -void safe_build_subdir_list (Glib::RefPtr &dir, std::vector &subDirs, bool add_hidden) -{ - Glib::RefPtr dirList; - - if (dir) { - // CD-ROMs with no drive inserted are reported, but do not exist, causing RT to crash - if (!safe_file_test(dir->get_path(), Glib::FILE_TEST_EXISTS)) { - return; - } - - SAFE_ENUMERATOR_CODE_START("standard::name,standard::type,standard::is-hidden") - - if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || add_hidden)) { - subDirs.push_back (info->get_name()); - } - - SAFE_ENUMERATOR_CODE_END; - } -} - -/* - * For an unknown reason, Glib::filename_to_utf8 doesn't work on Windows, so we're using - * Glib::filename_to_utf8 for Linux/Apple and Glib::locale_to_utf8 for Windows - */ -Glib::ustring safe_filename_to_utf8 (const std::string& src) -{ - Glib::ustring utf8_str; - -#ifdef WIN32 - - try { - utf8_str = Glib::locale_to_utf8(src); - } catch (const Glib::Error& e) { - utf8_str = Glib::convert_with_fallback(src, "UTF-8", "ISO-8859-1", "?"); - } - -#else - - utf8_str = Glib::filename_to_utf8(src); - -#endif - - return utf8_str; -} - -Glib::ustring safe_locale_to_utf8 (const std::string& src) -{ - Glib::ustring utf8_str; - - try { - utf8_str = Glib::locale_to_utf8(src); - } catch (const Glib::Error& e) { - utf8_str = Glib::convert_with_fallback(src, "UTF-8", "ISO-8859-1", "?"); - } - - return utf8_str; -} - -std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str) -{ - std::string str; - - try { - str = Glib::locale_from_utf8(utf8_str); - } catch (Glib::Error&) {} - - return str; -} - -bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8) -{ - std::string cmd; - bool success = false; - - try { - cmd = Glib::filename_from_utf8(cmd_utf8); - printf ("command line: %s\n", cmd.c_str()); - Glib::spawn_command_line_async (cmd.c_str()); - success = true; - } catch (Glib::Exception& ex) { - printf ("%s\n", ex.what().c_str()); - } - - return success; -} - -bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8) -{ - int exitStatus = -1; - - try { - //cmd = Glib::filename_from_utf8(cmd_utf8); - printf ("command line: %s\n", cmd_utf8.c_str()); - - // if it crashes here on windows, make sure you have the GTK runtime files gspawn-win32-helper*.exe files in RT directory - Glib::spawn_command_line_sync (cmd_utf8, NULL, NULL, &exitStatus); - } catch (Glib::Exception& ex) { - printf ("%s\n", ex.what().c_str()); - } - - return (exitStatus == 0); -} - -// Opens a file for binary writing and request exclusive lock (cases were you need "wb" mode plus locking) -// (Important on Windows to prevent Explorer to crash RT when parallel scanning e.g. a currently written image file) -FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname) -{ - FILE* f = NULL; - -#ifdef WIN32 - // g_fopen just uses _wfopen internally on Windows, does not lock access and has no options to set this - // so use a native function to work around this problem - wchar_t *wFname = (wchar_t*)g_utf8_to_utf16 (fname.c_str(), -1, NULL, NULL, NULL); - HANDLE hFile = CreateFileW(wFname, GENERIC_READ | GENERIC_WRITE, 0 /* no sharing allowed */, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - g_free(wFname); - - if (hFile == INVALID_HANDLE_VALUE) { - f = NULL; - } else { - f = _fdopen( _open_osfhandle((intptr_t)hFile, 0) , "wb"); - } - -#else - f = safe_g_fopen(fname, "wb"); -#endif - - return f; -} - -// Covers old UNIX ::open, which expects ANSI instead of UTF8 on Windows -int safe_open_ReadOnly(const char *fname) -{ - int fd = -1; - -#ifdef WIN32 - // First convert UTF8 to UTF16, then use Windows function to open - wchar_t *wFname = (wchar_t*)g_utf8_to_utf16 (fname, -1, NULL, NULL, NULL); - HANDLE hFile = CreateFileW(wFname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - g_free(wFname); - - // convert back to old file descriptor format - if (hFile != INVALID_HANDLE_VALUE) { - fd = _open_osfhandle((intptr_t)hFile, 0); - } - -#else - fd = ::open(fname, O_RDONLY); -#endif - - return fd; -} - - -FILE * safe_g_fopen(const Glib::ustring& src, const gchar *mode) -{ - return g_fopen(src.c_str(), mode); -} - -bool safe_file_test (const Glib::ustring& filename, Glib::FileTest test) -{ - return Glib::file_test (filename, test); -} - -int safe_g_remove(const Glib::ustring& filename) -{ - return ::g_remove(filename.c_str()); -} - -int safe_g_rename(const Glib::ustring& oldFilename, const Glib::ustring& newFilename) -{ - return ::g_rename(oldFilename.c_str(), newFilename.c_str()); -} - -int safe_g_mkdir_with_parents(const Glib::ustring& dirName, int mode) -{ - return ::g_mkdir_with_parents(dirName.c_str(), mode); -} - -Glib::ustring safe_get_user_picture_dir() -{ -#ifdef WIN32 - // get_user_special_dir/pictures crashes on some Windows configurations. - // so we use the safe native functions here - WCHAR pathW[MAX_PATH] = {0}; - - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_MYPICTURES, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - return Glib::ustring(pathA); - } else { - return Glib::ustring("C:\\"); - } - -#else - - return Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES); - -#endif -} - -Glib::ustring safe_get_user_home_dir() -{ -#ifdef WIN32 - // get_user_special_dir/pictures crashes on some Windows configurations. - // so we use the safe native functions here - WCHAR pathW[MAX_PATH] = {0}; - - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PERSONAL, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - return Glib::ustring(pathA); - } else { - return Glib::ustring("C:\\"); - } - -#else - - return Glib::get_home_dir(); - -#endif -} - -#ifdef WIN32 -Glib::ustring safe_get_user_profile_dir() -{ - WCHAR pathW[MAX_PATH] = {0}; - - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PROFILE, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - return Glib::ustring(pathA); - } else { - return Glib::ustring("C:\\"); - } -} -#endif - - -Glib::ustring safe_get_user_desktop_dir() -{ -#ifdef WIN32 - // get_user_special_dir/pictures crashes on some Windows configurations. - // so we use the safe native functions here - WCHAR pathW[MAX_PATH] = {0}; - - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_DESKTOP, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - return Glib::ustring(pathA); - } else { - return Glib::ustring("C:\\"); - } - -#else - - return Glib::get_user_special_dir (G_USER_DIRECTORY_DESKTOP); - -#endif -} - -#ifdef WIN32 -/* - * Test if the path is a root path based on the content of the string - * - * Warning: this function is a workaround for Windows platform, and not necessarily bullet proof - */ -bool safe_is_shortcut_dir (const Glib::ustring& path) -{ - return PathIsRootA(path.c_str()) || safe_get_user_home_dir() == path || safe_get_user_desktop_dir() == path || safe_get_user_profile_dir() == path; // || safe_get_user_picture_dir() == path; -} -#endif diff --git a/rtengine/safegtk.h b/rtengine/safegtk.h deleted file mode 100644 index 768d55148..000000000 --- a/rtengine/safegtk.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef SAFE_GTK_H_INCLUDED -#define SAFE_GTK_H_INCLUDED - -#include -#include -#include - -Glib::RefPtr safe_create_from_file(const Glib::ustring& filename); -Cairo::RefPtr safe_create_from_png(const Glib::ustring& filename); - -Glib::RefPtr safe_query_file_info (Glib::RefPtr &file); -void safe_build_file_list (Glib::RefPtr &dir, std::vector &names, const Glib::ustring &directory = "", const std::vector *extensions = NULL); -void safe_build_subdir_list (Glib::RefPtr &dir, std::vector &subDirs, bool add_hidden); - -bool safe_spawn_command_line_async (const Glib::ustring& cmd_utf8); -bool safe_spawn_command_line_sync (const Glib::ustring& cmd_utf8); - -Glib::ustring safe_filename_to_utf8 (const std::string& src); -Glib::ustring safe_locale_to_utf8 (const std::string& src); // from rtengine -std::string safe_locale_from_utf8 (const Glib::ustring& utf8_str); -std::string safe_filename_from_utf8 (const Glib::ustring& utf8_str); - -FILE * safe_g_fopen(const Glib::ustring& src, const gchar *mode); -FILE * safe_g_fopen_WriteBinLock(const Glib::ustring& fname); -int safe_open_ReadOnly(const char *fname); - -bool safe_file_test (const Glib::ustring& filename, Glib::FileTest test); -int safe_g_remove(const Glib::ustring& filename); -int safe_g_rename(const Glib::ustring& oldFilename, const Glib::ustring& newFilename); -int safe_g_mkdir_with_parents(const Glib::ustring& dirName, int mode); - -Glib::ustring safe_get_user_picture_dir(); -Glib::ustring safe_get_user_home_dir(); -Glib::ustring safe_get_user_desktop_dir(); - -#ifdef WIN32 -Glib::ustring safe_get_user_profile_dir(); -bool safe_is_shortcut_dir (const Glib::ustring& filename); -#endif - -#endif diff --git a/rtengine/safekeyfile.h b/rtengine/safekeyfile.h deleted file mode 100644 index 8a934240e..000000000 --- a/rtengine/safekeyfile.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef SAFE_KEY_FILE_H_INCLUDED -#define SAFE_KEY_FILE_H_INCLUDED - -#include -namespace rtengine -{ - -class SafeKeyFile : public Glib::KeyFile -{ -public : - -#ifdef GLIBMM_EXCEPTIONS_ENABLED -#define SAFE_KEY_FILE_METHOD_CODE(method,method_err) \ - do { try { res = Glib::KeyFile::method; }catch (const Glib::KeyFileError& e) { } ; \ - return res; }while(0) -#else -#define SAFE_KEY_FILE_METHOD_CODE(method,method_err) \ - do { std::auto_ptr error; \ - res = Glib::KeyFile::method_err; \ - if (error.get()){/* TODO */}; \ - return res;} while(0) -#endif //GLIBMM_EXCEPTIONS_ENABLED -#define SAFE_KEY_FILE_METHOD(method,method_err,ret_type) \ - { ret_type res = (ret_type)0; SAFE_KEY_FILE_METHOD_CODE(method,method_err);} - -#define SAFE_KEY_FILE_METHOD_NOINIT(method,method_err,ret_type) \ - { ret_type res; SAFE_KEY_FILE_METHOD_CODE(method,method_err);} - - Glib::ustring to_data() - SAFE_KEY_FILE_METHOD_NOINIT(to_data(), to_data(error), Glib::ustring); - - bool load_from_data(const Glib::ustring& data, Glib::KeyFileFlags flags = Glib::KEY_FILE_NONE) - SAFE_KEY_FILE_METHOD(load_from_data(data, flags), load_from_data(data, flags, error), bool); - - bool load_from_file(const std::string& filename, Glib::KeyFileFlags flags = Glib::KEY_FILE_NONE) - SAFE_KEY_FILE_METHOD(load_from_file(filename, flags), load_from_file(filename, flags, error), bool); - - bool has_key(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD(has_key(group_name, key), has_key(group_name, key, error), bool); - - bool get_boolean(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD(get_boolean(group_name, key), get_boolean(group_name, key, error), bool); - - int get_integer(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD(get_integer(group_name, key), get_integer(group_name, key, error), int); - - - - double get_double(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD(get_double(group_name, key), get_double(group_name, key, error), double); - - typedef std::vector DoubleArrayType; - - DoubleArrayType get_double_list(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD_NOINIT(get_double_list(group_name, key), get_double_list(group_name, key, error), DoubleArrayType); - - typedef std::vector IntArrayType; - - IntArrayType get_integer_list(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD_NOINIT(get_integer_list(group_name, key), get_integer_list(group_name, key, error), IntArrayType); - - Glib::ustring get_string(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD_NOINIT(get_string(group_name, key), get_string(group_name, key, error), Glib::ustring); - /* - double get_double(const Glib::ustring& group_name, const Glib::ustring& key) const { - Glib::ustring temp = get_string( group_name, key); - if(!temp.empty()) { - double tmpdbl; - if(sscanf(temp.c_str(), "%lf", &tmpdbl)) - return tmpdbl; - else - return 0.0; - } - return 0.0; - } - */ - typedef std::vector StringArrayType; - - StringArrayType get_string_list(const Glib::ustring& group_name, const Glib::ustring& key) const - SAFE_KEY_FILE_METHOD_NOINIT(get_string_list(group_name, key), get_string_list(group_name, key, error), StringArrayType); - /* - typedef std::vector DoubleArrayType; - - DoubleArrayType get_double_list(const Glib::ustring& group_name, const Glib::ustring& key) const { - StringArrayType temp = get_string_list(group_name, key); - DoubleArrayType tempdouble; - unsigned int n = temp.size(); - if(n) { - tempdouble.reserve(n); - for (unsigned int i=0; igetWidth(); + const int H = baseImg->getHeight(); + LabImage labcbdl(W, H); + ipf.rgb2lab(*baseImg, labcbdl, params.icm.working); + ipf.dirpyrequalizer (&labcbdl, 1); + ipf.lab2rgb(labcbdl, *baseImg, params.icm.working); + } + // update blurmap SHMap* shmap = NULL; @@ -982,9 +992,12 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p params.wavelet.getCurves(wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL ); + // directional pyramid wavelet - if((params.colorappearance.enabled && !settings->autocielab) || !params.colorappearance.enabled) { - ipf.dirpyrequalizer (labView, 1); //TODO: this is the luminance tonecurve, not the RGB one + if(params.dirpyrequalizer.cbdlMethod == "aft") { + if((params.colorappearance.enabled && !settings->autocielab) || !params.colorappearance.enabled) { + ipf.dirpyrequalizer (labView, 1); //TODO: this is the luminance tonecurve, not the RGB one + } } int kall = 2; diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index be442945d..f61d90c08 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -25,9 +25,11 @@ #include #include -#include "../rtgui/cacheimagedata.h" +#include + #include "rtexif.h" -#include "../rtengine/safegtk.h" + +#include "../rtgui/cacheimagedata.h" #include "../rtgui/version.h" #include "../rtgui/ppversion.h" @@ -247,17 +249,10 @@ void TagDirectory::printAll (unsigned int level) const * * @return True if everything went fine, false otherwise */ -bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, const CacheImageData* cfs, const bool flagMode, - rtengine::SafeKeyFile *keyFile, Glib::ustring tagDirName) const +bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, + const CacheImageData* cfs, const bool flagMode, Glib::KeyFile *keyFile, Glib::ustring tagDirName) const { - - rtengine::SafeKeyFile *kf; - - if (!keyFile) { - kf = new rtengine::SafeKeyFile(); - } else { - kf = keyFile; - } + const auto kf = keyFile ? keyFile : new Glib::KeyFile; if (!kf) { return false; @@ -274,7 +269,7 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring if (!keyFile) { // open the file in write mode - f = safe_g_fopen (commFName, "wt"); + f = g_fopen (commFName.c_str (), "wt"); if (f == NULL) { printf("TagDirectory::keyFileDump(\"%s\") >>> Error: unable to open file with write access!\n", commFName.c_str()); @@ -282,21 +277,25 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring return false; } - kf->set_string ("RT General", "CachePath", options.cacheBaseDir); - kf->set_string ("RT General", "AppVersion", VERSION); - kf->set_integer("RT General", "ProcParamsVersion", PPVERSION); - kf->set_string ("RT General", "ImageFileName", imageFName); - kf->set_string ("RT General", "OutputProfileFileName", profileFName); - kf->set_string ("RT General", "DefaultProcParams", defaultPParams); - kf->set_boolean("RT General", "FlaggingMode", flagMode); + try { - kf->set_double ("Common Data", "FNumber", cfs->fnumber); - kf->set_double ("Common Data", "Shutter", cfs->shutter); - kf->set_double ("Common Data", "FocalLength", cfs->focalLen); - kf->set_integer("Common Data", "ISO", cfs->iso); - kf->set_string ("Common Data", "Lens", cfs->lens); - kf->set_string ("Common Data", "Make", cfs->camMake); - kf->set_string ("Common Data", "Model", cfs->camModel); + kf->set_string ("RT General", "CachePath", options.cacheBaseDir); + kf->set_string ("RT General", "AppVersion", VERSION); + kf->set_integer("RT General", "ProcParamsVersion", PPVERSION); + kf->set_string ("RT General", "ImageFileName", imageFName); + kf->set_string ("RT General", "OutputProfileFileName", profileFName); + kf->set_string ("RT General", "DefaultProcParams", defaultPParams); + kf->set_boolean("RT General", "FlaggingMode", flagMode); + + kf->set_double ("Common Data", "FNumber", cfs->fnumber); + kf->set_double ("Common Data", "Shutter", cfs->shutter); + kf->set_double ("Common Data", "FocalLength", cfs->focalLen); + kf->set_integer("Common Data", "ISO", cfs->iso); + kf->set_string ("Common Data", "Lens", cfs->lens); + kf->set_string ("Common Data", "Make", cfs->camMake); + kf->set_string ("Common Data", "Model", cfs->camModel); + + } catch (Glib::KeyFileError&) {} } // recursively iterate over the tag list @@ -308,10 +307,15 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring // Accumulating the TagDirectories to dump later tagDirPaths.push_back( Glib::ustring( tagDirName + "/" + getDumpKey(tags[i]->getID(), tagName) ) ); tagDirList.push_back(tags[i]->getDirectory(j)); - kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), "$subdir"); + + try { + kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), "$subdir"); + } catch (Glib::KeyFileError&) {} } else { - kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), tags[i]->valueToString()); + try { + kf->set_string (tagDirName, getDumpKey(tags[i]->getID(), tagName), tags[i]->valueToString()); + } catch (Glib::KeyFileError&) {} } } @@ -321,7 +325,10 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring } if (!keyFile) { - fprintf (f, "%s", kf->to_data().c_str()); + try { + fprintf (f, "%s", kf->to_data().c_str()); + } catch (Glib::KeyFileError&) {} + fclose (f); delete kf; } diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index d7c13f77a..2d6c800fc 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -29,7 +29,6 @@ #include #include #include "../rtengine/procparams.h" -#include "../rtengine/safekeyfile.h" class CacheImageData; @@ -156,7 +155,7 @@ public: virtual void printAll (unsigned int level = 0) const; // reentrant debug function, keep level=0 on first call ! virtual bool CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, - const CacheImageData* cfs, const bool flagMode, rtengine::SafeKeyFile *keyFile = NULL, Glib::ustring tagDirName = "") const; + const CacheImageData* cfs, const bool flagMode, Glib::KeyFile *keyFile = NULL, Glib::ustring tagDirName = "") const; virtual void sort (); }; diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index 4ae2976b3..bd1f5e439 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -32,7 +32,6 @@ #include "filecatalog.h" #include "batchqueuebuttonset.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" using namespace std; @@ -372,7 +371,7 @@ Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename strftime (stringTimestamp, sizeof(stringTimestamp), "_%Y%m%d%H%M%S_", timeinfo); Glib::ustring savedParamPath; savedParamPath = options.rtdir + "/batch/"; - safe_g_mkdir_with_parents (savedParamPath, 0755); + g_mkdir_with_parents (savedParamPath.c_str (), 0755); savedParamPath += Glib::path_get_basename (filename); savedParamPath += stringTimestamp; savedParamPath += paramFileExtension; @@ -381,8 +380,11 @@ Glib::ustring BatchQueue::getTempFilenameForParams( const Glib::ustring filename int cancelItemUI (void* data) { - safe_g_remove( (static_cast(data))->savedParamsFile ); - delete static_cast(data); + const auto bqe = static_cast(data); + + g_remove (bqe->savedParamsFile.c_str ()); + delete bqe; + return 0; } @@ -667,24 +669,31 @@ rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) processing->removeButtonSet (); } - if (saveBatchQueue( )) { - safe_g_remove( processedParams ); - // Delete all files in directory \batch when finished, just to be sure to remove zombies + if (saveBatchQueue ()) { + ::g_remove (processedParams.c_str ()); - // Not sure that locking is necessary, but it should be safer - MYREADERLOCK(l, entryRW); + // Delete all files in directory batch when finished, just to be sure to remove zombies + auto isEmpty = false; - if( fd.empty() ) { - MYREADERLOCK_RELEASE(l); + { + MYREADERLOCK(l, entryRW); + isEmpty = fd.empty(); + } - std::vector names; - Glib::ustring batchdir = Glib::build_filename(options.rtdir, "batch"); - Glib::RefPtr dir = Gio::File::create_for_path (batchdir); - safe_build_file_list (dir, names, batchdir); + if (isEmpty) { - for(std::vector::iterator iter = names.begin(); iter != names.end(); iter++ ) { - safe_g_remove( *iter ); - } + const auto batchdir = Glib::build_filename (options.rtdir, "batch"); + + try { + + auto dir = Gio::File::create_for_path (batchdir); + auto enumerator = dir->enumerate_children ("standard::name"); + + while (auto file = enumerator->next_file ()) { + ::g_remove (Glib::build_filename (batchdir, file->get_name ()).c_str ()); + } + + } catch (Glib::Exception&) {} } } @@ -830,8 +839,8 @@ Glib::ustring BatchQueue::autoCompleteFileName (const Glib::ustring& fileName, c Glib::ustring fname; // create directory, if does not exist - if (safe_g_mkdir_with_parents (dstdir, 0755) ) { - return ""; + if (g_mkdir_with_parents (dstdir.c_str (), 0755)) { + return Glib::ustring (); } // In overwrite mode we TRY to delete the old file first. @@ -845,10 +854,10 @@ Glib::ustring BatchQueue::autoCompleteFileName (const Glib::ustring& fileName, c fname = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, format); } - int fileExists = safe_file_test (fname, Glib::FILE_TEST_EXISTS); + int fileExists = Glib::file_test (fname, Glib::FILE_TEST_EXISTS); if (inOverwriteMode && fileExists) { - if (safe_g_remove(fname) == -1) { + if (::g_remove (fname.c_str ()) != 0) { inOverwriteMode = false; // failed to delete- revert to old naming scheme } else { fileExists = false; // deleted now diff --git a/rtgui/batchqueuebuttonset.cc b/rtgui/batchqueuebuttonset.cc index f3023d838..fefcdf3c9 100644 --- a/rtgui/batchqueuebuttonset.cc +++ b/rtgui/batchqueuebuttonset.cc @@ -17,8 +17,9 @@ * along with RawTherapee. If not, see . */ #include "batchqueuebuttonset.h" + #include "multilangmgr.h" -#include "../rtengine/safegtk.h" +#include "rtimage.h" bool BatchQueueButtonSet::iconsLoaded = false; @@ -30,9 +31,9 @@ BatchQueueButtonSet::BatchQueueButtonSet (BatchQueueEntry* myEntry) { if (!iconsLoaded) { - cancelIcon = safe_create_from_png ("gtk-close.png"); - headIcon = safe_create_from_png ("toleftend.png"); - tailIcon = safe_create_from_png ("torightend.png"); + cancelIcon = RTImage::createFromPng ("gtk-close.png"); + headIcon = RTImage::createFromPng ("toleftend.png"); + tailIcon = RTImage::createFromPng ("torightend.png"); iconsLoaded = true; } diff --git a/rtgui/batchqueueentry.cc b/rtgui/batchqueueentry.cc index 462452c57..f130df5ee 100644 --- a/rtgui/batchqueueentry.cc +++ b/rtgui/batchqueueentry.cc @@ -17,13 +17,14 @@ * along with RawTherapee. If not, see . */ #include "batchqueueentry.h" -#include "thumbbrowserbase.h" #include + #include "guiutils.h" #include "threadutils.h" -#include "../rtengine/safegtk.h" +#include "rtimage.h" #include "multilangmgr.h" +#include "thumbbrowserbase.h" bool BatchQueueEntry::iconsLoaded(false); Glib::RefPtr BatchQueueEntry::savedAsIcon; @@ -46,7 +47,7 @@ BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine: #endif if (!iconsLoaded) { - savedAsIcon = safe_create_from_file ("gtk-save.png"); + savedAsIcon = RTImage::createFromFile ("gtk-save.png"); iconsLoaded = true; } diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 2775ba980..488ef7e41 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -22,7 +22,6 @@ #include "multilangmgr.h" #include "rtwindow.h" #include "soundman.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" struct BQProcessLoaded { @@ -39,7 +38,7 @@ int processLoadedBatchQueueUIThread (void* data) static Glib::ustring makeFolderLabel(Glib::ustring path) { - if (!safe_file_test (path, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) { return "(" + M("GENERAL_NONE") + ")"; } @@ -116,7 +115,7 @@ BatchQueuePanel::BatchQueuePanel (FileCatalog* aFileCatalog) outdirFolder->signal_current_folder_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::pathFolderChanged)); outdirFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT")); - if (safe_file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR)) { outdirFolder->set_current_folder (options.savePathFolder); } @@ -347,8 +346,8 @@ void BatchQueuePanel::pathFolderButtonPressed () int result = fc.run(); if (result == Gtk::RESPONSE_OK) { - if (safe_file_test(fc.get_filename(), Glib::FILE_TEST_IS_DIR)) { - options.savePathFolder = fc.get_filename(); + if (Glib::file_test(fc.get_current_folder(), Glib::FILE_TEST_IS_DIR)) { + options.savePathFolder = fc.get_filename (); outdirFolderButton->set_label(makeFolderLabel(options.savePathFolder)); } } diff --git a/rtgui/bayerpreprocess.cc b/rtgui/bayerpreprocess.cc index cce51cca3..51a0cb62a 100644 --- a/rtgui/bayerpreprocess.cc +++ b/rtgui/bayerpreprocess.cc @@ -18,7 +18,6 @@ */ #include "bayerpreprocess.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index ca376eb64..ee9b4fc4d 100644 --- a/rtgui/bayerrawexposure.cc +++ b/rtgui/bayerrawexposure.cc @@ -18,7 +18,6 @@ */ #include "bayerrawexposure.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 4b276a03b..75a6ab75a 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -19,8 +19,6 @@ #include "cacheimagedata.h" #include #include -#include "../rtengine/safekeyfile.h" -#include "../rtengine/safegtk.h" #include "version.h" #include @@ -36,7 +34,8 @@ CacheImageData::CacheImageData () int CacheImageData::load (const Glib::ustring& fname) { setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - rtengine::SafeKeyFile keyFile; + + Glib::KeyFile keyFile; try { if (keyFile.load_from_file (fname)) { @@ -165,10 +164,6 @@ int CacheImageData::load (const Glib::ustring& fname) if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) { thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType"); } - - if (keyFile.has_key ("ExtraRawInfo", "ThumbImageOffset")) { - thumbOffset = keyFile.get_integer ("ExtraRawInfo", "ThumbImageOffset"); - } } else { rotate = 0; thumbImgType = 0; @@ -195,21 +190,15 @@ int CacheImageData::load (const Glib::ustring& fname) int CacheImageData::save (const Glib::ustring& fname) { - rtengine::SafeKeyFile keyFile; + Glib::ustring keyData; - if (safe_file_test(fname, Glib::FILE_TEST_EXISTS)) { - try { - keyFile.load_from_file (fname); - } catch (Glib::Error &err) { - if (options.rtSettings.verbose) { - printf("CacheImageData::save / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); - } - } catch (...) { - if (options.rtSettings.verbose) { - printf("CacheImageData::save / Unknown exception while trying to save \"%s\"!\n", fname.c_str()); - } - } - } + try { + + Glib::KeyFile keyFile; + + try { + keyFile.load_from_file (fname); + } catch (Glib::Error&) {} keyFile.set_string ("General", "MD5", md5); keyFile.set_string ("General", "Version", VERSION); // Application's version @@ -254,10 +243,25 @@ int CacheImageData::save (const Glib::ustring& fname) if (format == FT_Raw) { keyFile.set_integer ("ExtraRawInfo", "ThumbImageType", thumbImgType); - keyFile.set_integer ("ExtraRawInfo", "ThumbImageOffset", thumbOffset); } - FILE *f = safe_g_fopen (fname, "wt"); + keyData = keyFile.to_data (); + + } catch (Glib::Error &err) { + if (options.rtSettings.verbose) { + printf("CacheImageData::save / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); + } + } catch (...) { + if (options.rtSettings.verbose) { + printf("CacheImageData::save / Unknown exception while trying to save \"%s\"!\n", fname.c_str()); + } + } + + if (keyData.empty ()) { + return 1; + } + + FILE *f = g_fopen (fname.c_str (), "wt"); if (!f) { if (options.rtSettings.verbose) { @@ -266,7 +270,7 @@ int CacheImageData::save (const Glib::ustring& fname) return 1; } else { - fprintf (f, "%s", keyFile.to_data().c_str()); + fprintf (f, "%s", keyData.c_str ()); fclose (f); return 0; } diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 91a31ce4f..f655bd88b 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -65,7 +65,6 @@ public: // additional info on raw images int rotate; int thumbImgType; - int thumbOffset; enum { FULL_THUMBNAIL = 0, // was the thumbnail generated from whole file diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 6b07761f8..e75c1d7a2 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -16,19 +16,21 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include "cropwindow.h" + #include -#include "cropwindow.h" -#include "options.h" -#include "guiutils.h" -#include "threadutils.h" #include "../rtengine/mytime.h" -#include "imagearea.h" -#include "cursormanager.h" -#include "../rtengine/safegtk.h" #include "../rtengine/rt_math.h" #include "../rtengine/dcrop.h" +#include "guiutils.h" +#include "threadutils.h" +#include "rtimage.h" +#include "cursormanager.h" +#include "options.h" +#include "imagearea.h" + using namespace rtengine; struct ZoomStep { @@ -84,11 +86,11 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, titleHeight = ih; - bZoomOut = new LWButton (safe_create_from_png ("gtk-zoom-out-small.png"), 0, NULL, LWButton::Left, LWButton::Center, "Zoom Out"); - bZoomIn = new LWButton (safe_create_from_png ("gtk-zoom-in-small.png"), 1, NULL, LWButton::Left, LWButton::Center, "Zoom In"); - bZoom100 = new LWButton (safe_create_from_png ("gtk-zoom-100-small.png"), 2, NULL, LWButton::Left, LWButton::Center, "Zoom 100/%"); - //bZoomFit = new LWButton (safe_create_from_png ("gtk-zoom-fit.png"), 3, NULL, LWButton::Left, LWButton::Center, "Zoom Fit"); - bClose = new LWButton (safe_create_from_png ("gtk-close-small.png"), 4, NULL, LWButton::Right, LWButton::Center, "Close"); + bZoomOut = new LWButton (RTImage::createFromPng ("gtk-zoom-out-small.png"), 0, NULL, LWButton::Left, LWButton::Center, "Zoom Out"); + bZoomIn = new LWButton (RTImage::createFromPng ("gtk-zoom-in-small.png"), 1, NULL, LWButton::Left, LWButton::Center, "Zoom In"); + bZoom100 = new LWButton (RTImage::createFromPng ("gtk-zoom-100-small.png"), 2, NULL, LWButton::Left, LWButton::Center, "Zoom 100/%"); + //bZoomFit = new LWButton (RTImage::createFromPng ("gtk-zoom-fit.png"), 3, NULL, LWButton::Left, LWButton::Center, "Zoom Fit"); + bClose = new LWButton (RTImage::createFromPng ("gtk-close-small.png"), 4, NULL, LWButton::Right, LWButton::Center, "Close"); buttonSet.add (bZoomOut); buttonSet.add (bZoomIn); diff --git a/rtgui/cursormanager.cc b/rtgui/cursormanager.cc index f29d0f6ec..295061ea2 100644 --- a/rtgui/cursormanager.cc +++ b/rtgui/cursormanager.cc @@ -17,8 +17,8 @@ * along with RawTherapee. If not, see . */ #include "cursormanager.h" + #include "options.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" CursorManager mainWindowCursorManager; @@ -51,14 +51,14 @@ void CursorManager::init (Glib::RefPtr mainWindow) cAdd = Gdk::Cursor::create (display, Gdk::PLUS); cWait = Gdk::Cursor::create (display, Gdk::CLOCK); - Glib::RefPtr hand = safe_create_from_file("cross.png"); - Glib::RefPtr close_hand = safe_create_from_file("closedhand.png"); - Glib::RefPtr wbpick = safe_create_from_file("gtk-color-picker-small.png"); - Glib::RefPtr empty = safe_create_from_file("empty.png"); - Glib::RefPtr move2D = safe_create_from_file("move-2D.png"); - Glib::RefPtr move1DH = safe_create_from_file("move-1D-h.png"); - Glib::RefPtr move1DV = safe_create_from_file("move-1D-v.png"); - Glib::RefPtr moveRotate = safe_create_from_file("move-rotate.png"); + Glib::RefPtr hand = RTImage::createFromFile ("cross.png"); + Glib::RefPtr close_hand = RTImage::createFromFile ("closedhand.png"); + Glib::RefPtr wbpick = RTImage::createFromFile ("gtk-color-picker-small.png"); + Glib::RefPtr empty = RTImage::createFromFile ("empty.png"); + Glib::RefPtr move2D = RTImage::createFromFile ("move-2D.png"); + Glib::RefPtr move1DH = RTImage::createFromFile ("move-1D-h.png"); + Glib::RefPtr move1DV = RTImage::createFromFile ("move-1D-v.png"); + Glib::RefPtr moveRotate = RTImage::createFromFile ("move-rotate.png"); cHand = hand ? Gdk::Cursor::create (cAdd->get_display(), hand, 10, 10) : Gdk::Cursor::create (cAdd->get_display(), Gdk::HAND2); cClosedHand = close_hand ? Gdk::Cursor::create (cAdd->get_display(), close_hand, 10, 10) : Gdk::Cursor::create (cAdd->get_display(), Gdk::HAND2); diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc index 89c66d6b8..4726074de 100644 --- a/rtgui/curveeditorgroup.cc +++ b/rtgui/curveeditorgroup.cc @@ -24,7 +24,6 @@ #include "diagonalcurveeditorsubgroup.h" #include "flatcurveeditorsubgroup.h" #include "multilangmgr.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" CurveEditorGroup::CurveEditorGroup (Glib::ustring& curveDir, Glib::ustring groupLabel) : curveDir(curveDir), curve_reset(NULL), diff --git a/rtgui/darkframe.cc b/rtgui/darkframe.cc index 954ca1835..d13f8e652 100644 --- a/rtgui/darkframe.cc +++ b/rtgui/darkframe.cc @@ -19,7 +19,6 @@ #include "darkframe.h" #include "options.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include "rtimage.h" @@ -81,7 +80,7 @@ void DarkFrame::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi dfAuto->set_inconsistent(!pedited->raw.dfAuto ); } - if (safe_file_test (pp->raw.dark_frame, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (pp->raw.dark_frame, Glib::FILE_TEST_EXISTS)) { darkFrameFile->set_filename (pp->raw.dark_frame); } else { darkFrameReset(); diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index 816fa1803..454383075 100644 --- a/rtgui/dirbrowser.cc +++ b/rtgui/dirbrowser.cc @@ -17,27 +17,57 @@ * along with RawTherapee. If not, see . */ #include "dirbrowser.h" + +#include + #ifdef WIN32 #define _WIN32_WINNT 0x0600 #include #endif -#include "options.h" -#include "multilangmgr.h" -#include "../rtengine/safegtk.h" -#include #include "guiutils.h" #include "rtimage.h" +#include "multilangmgr.h" +#include "options.h" -#define CHECKTIME 5000 +namespace +{ + +std::vector listSubDirs (const Glib::RefPtr& dir, bool addHidden) +{ + std::vector subDirs; + + try { + + // CD-ROM with no disc inserted are reported, but do not exist. + if (!Glib::file_test (dir->get_path (), Glib::FILE_TEST_EXISTS)) { + return subDirs; + } + + auto enumerator = dir->enumerate_children ("standard::name,standard::type,standard::is-hidden"); + + while (auto file = enumerator->next_file ()) { + if (file->get_file_type () != Gio::FILE_TYPE_DIRECTORY) { + continue; + } + if (!addHidden && file->is_hidden ()) { + continue; + } + subDirs.push_back (file->get_name ()); + } + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to list subdirectories of \"" << dir << "\": " << exception.what () << std::endl; + } -struct DirNameComparator { - template - bool operator()(T const &firstDir, T const &secondDir) const - { - return options.dirBrowserSortType == Gtk::SORT_ASCENDING ? firstDir < secondDir : firstDir > secondDir; } -}; + + return subDirs; +} + +} DirBrowser::DirBrowser () : dirTreeModel(), dtColumns(), @@ -71,13 +101,13 @@ DirBrowser::DirBrowser () : dirTreeModel(), void DirBrowser::fillDirTree () { - openfolder = safe_create_from_file ("gtk-open.png"); - closedfolder = safe_create_from_file ("folder.png"); - icdrom = safe_create_from_file ("drive-optical.png"); - ifloppy = safe_create_from_file ("drive-removable-media.png"); - ihdd = safe_create_from_file ("drive-harddisk.png"); - iremovable = safe_create_from_file ("media-usb.png"); - inetwork = safe_create_from_file ("network.png"); + openfolder = RTImage::createFromFile ("gtk-open.png"); + closedfolder = RTImage::createFromFile ("folder.png"); + icdrom = RTImage::createFromFile ("drive-optical.png"); + ifloppy = RTImage::createFromFile ("drive-removable-media.png"); + ihdd = RTImage::createFromFile ("drive-harddisk.png"); + iremovable = RTImage::createFromFile ("media-usb.png"); + inetwork = RTImage::createFromFile ("network.png"); //Create the Tree model: dirTreeModel = Gtk::TreeStore::create(dtColumns); @@ -220,7 +250,7 @@ void DirBrowser::fillRoot () } // since sigc++ is not thread safe, we have to use the glib function - g_timeout_add (CHECKTIME, updateVolumesUI, this); + g_timeout_add (5000, updateVolumesUI, this); #else Gtk::TreeModel::Row rootRow = *(dirTreeModel->append()); rootRow[dtColumns.filename] = "/"; @@ -243,19 +273,15 @@ void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk:: // We will disable model's sorting because it decreases speed of inserting new items // in list tree dramatically. Therefore will do: // 1) Disable sorting in model - // 2) Manually sort data by DirNameComparator + // 2) Manually sort data in the order determined by the options // 3) Enable sorting in model again for UI (sorting by click on header) int prevSortColumn; Gtk::SortType prevSortType; dirTreeModel->get_sort_column_id(prevSortColumn, prevSortType); dirTreeModel->set_sort_column(Gtk::TreeSortable::DEFAULT_UNSORTED_COLUMN_ID, Gtk::SORT_ASCENDING); - typedef std::vector DirPathType; - - DirPathType subDirs; - Glib::RefPtr dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); - - safe_build_subdir_list (dir, subDirs, options.fbShowHidden); + auto dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); + auto subDirs = listSubDirs (dir, options.fbShowHidden); if (subDirs.empty()) { dirtree->collapse_row(path); @@ -263,14 +289,22 @@ void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk:: Gtk::TreeNodeChildren children = iter->children(); std::list forErase(children.begin(), children.end()); - DirNameComparator comparator; - sort(subDirs.begin(), subDirs.end(), comparator); + std::sort (subDirs.begin (), subDirs.end (), [] (const Glib::ustring& firstDir, const Glib::ustring& secondDir) + { + switch (options.dirBrowserSortType) { + default: + case Gtk::SORT_ASCENDING: + return firstDir < secondDir; + case Gtk::SORT_DESCENDING: + return firstDir > secondDir; + } + }); - for (DirPathType::const_iterator it = subDirs.begin(), end = subDirs.end(); it != end; ++it) { + for (auto it = subDirs.begin(), end = subDirs.end(); it != end; ++it) { addDir(iter, *it); } - for (std::list::const_iterator it = forErase.begin(), end = forErase.end(); it != end; ++it) { + for (auto it = forErase.begin(), end = forErase.end(); it != end; ++it) { dirTreeModel->erase(*it); } @@ -299,8 +333,8 @@ void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) change = false; for (Gtk::TreeModel::iterator it = iter->children().begin(); it != iter->children().end(); it++) - if (!safe_file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_EXISTS) - || !safe_file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_EXISTS) + || !Glib::file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_IS_DIR)) { GThreadLock lock; dirTreeModel->erase (it); change = true; @@ -309,9 +343,8 @@ void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) } // test if new files are created - std::vector subDirs; - Glib::RefPtr dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); - safe_build_subdir_list (dir, subDirs, options.fbShowHidden); + auto dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname)); + auto subDirs = listSubDirs (dir, options.fbShowHidden); for (int i = 0; i < subDirs.size(); i++) { bool found = false; @@ -345,7 +378,7 @@ void DirBrowser::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewC Glib::ustring dname = dirTreeModel->get_iter (path)->get_value (dtColumns.dirname); - if (safe_file_test (dname, Glib::FILE_TEST_IS_DIR)) + if (Glib::file_test (dname, Glib::FILE_TEST_IS_DIR)) dirSelectionSignal (dname, Glib::ustring()); } @@ -442,7 +475,7 @@ void DirBrowser::open (const Glib::ustring& dirname, const Glib::ustring& fileNa void DirBrowser::file_changed (const Glib::RefPtr& file, const Glib::RefPtr& other_file, Gio::FileMonitorEvent event_type, const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirName) { - if (!file || !safe_file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type == Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) { + if (!file || !Glib::file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type == Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) { return; } diff --git a/rtgui/dirpyrequalizer.cc b/rtgui/dirpyrequalizer.cc index d872c89ee..9a051f137 100644 --- a/rtgui/dirpyrequalizer.cc +++ b/rtgui/dirpyrequalizer.cc @@ -51,6 +51,24 @@ DirPyrEqualizer::DirPyrEqualizer () : FoldableToolPanel(this, "dirpyrequalizer", Color::hsv2rgb01(0.3240, 0.5, 0.5, r, g, b); milestones.push_back( GradientMilestone(1. , r, g, b) ); // hsv: 0.324 rad: 2.5 + Gtk::VBox * cbVBox = Gtk::manage ( new Gtk::VBox()); + cbVBox->set_border_width(4); + cbVBox->set_spacing(2); + + cdbox = Gtk::manage (new Gtk::HBox ()); + labmcd = Gtk::manage (new Gtk::Label (M("TP_CBDL_METHOD") + ":")); + cdbox->pack_start (*labmcd, Gtk::PACK_SHRINK, 1); + + cbdlMethod = Gtk::manage (new MyComboBoxText ()); + cbdlMethod->append (M("TP_CBDL_BEF")); + cbdlMethod->append (M("TP_CBDL_AFT")); + cbdlMethod->set_active(0); + cbdlMethodConn = cbdlMethod->signal_changed().connect ( sigc::mem_fun(*this, &DirPyrEqualizer::cbdlMethodChanged) ); + cbdlMethod->set_tooltip_markup (M("TP_CBDL_METHOD_TOOLTIP")); + cdbox->pack_start(*cbdlMethod); + cbVBox->pack_start(*cdbox); + pack_start(*cbVBox); + setEnabledTooltipMarkup(M("TP_SHARPENING_TOOLTIP")); Gtk::HBox * buttonBox1 = Gtk::manage (new Gtk::HBox(true, 10)); @@ -145,12 +163,17 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) { disableListener (); + cbdlMethodConn.block(true); if (pedited) { set_inconsistent (multiImage && !pedited->dirpyrequalizer.enabled); gamutlab->set_inconsistent (!pedited->dirpyrequalizer.gamutlab); + if (!pedited->dirpyrequalizer.cbdlMethod) { + cbdlMethod->set_active_text(M("GENERAL_UNCHANGED")); + } + for(int i = 0; i < 6; i++) { multiplier[i]->setEditedState (pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited); } @@ -186,6 +209,15 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) skinprotect->setValue(pp->dirpyrequalizer.skinprotect); hueskin->setValue(pp->dirpyrequalizer.hueskin); + if (pp->dirpyrequalizer.cbdlMethod == "bef") { + cbdlMethod->set_active (0); + } else if (pp->dirpyrequalizer.cbdlMethod == "aft") { + cbdlMethod->set_active (1); + } + + cbdlMethodChanged (); + cbdlMethodConn.block(false); + enableListener (); } @@ -207,6 +239,7 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) pedited->dirpyrequalizer.enabled = !get_inconsistent(); pedited->dirpyrequalizer.hueskin = hueskin->getEditedState (); + pedited->dirpyrequalizer.cbdlMethod = cbdlMethod->get_active_text() != M("GENERAL_UNCHANGED"); for(int i = 0; i < 6; i++) { pedited->dirpyrequalizer.mult[i] = multiplier[i]->getEditedState(); @@ -217,6 +250,13 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) // pedited->dirpyrequalizer.algo = algo->get_active_text()!=M("GENERAL_UNCHANGED"); } + + if (cbdlMethod->get_active_row_number() == 0) { + pp->dirpyrequalizer.cbdlMethod = "bef"; + } else if (cbdlMethod->get_active_row_number() == 1) { + pp->dirpyrequalizer.cbdlMethod = "aft"; + } + /* if (algo->get_active_row_number()==0) pp->dirpyrequalizer.algo = "FI"; else if (algo->get_active_row_number()==1) @@ -281,6 +321,16 @@ void DirPyrEqualizer::setBatchMode (bool batchMode) // algo->append (M("GENERAL_UNCHANGED")); } +void DirPyrEqualizer::cbdlMethodChanged() +{ + + if (listener) { + listener->panelChanged (EvcbdlMethod, cbdlMethod->get_active_text ()); + } +} + + + void DirPyrEqualizer::adjusterChanged (Adjuster* a, double newval) { diff --git a/rtgui/dirpyrequalizer.h b/rtgui/dirpyrequalizer.h index 6c0a4613d..9b806989c 100644 --- a/rtgui/dirpyrequalizer.h +++ b/rtgui/dirpyrequalizer.h @@ -45,6 +45,10 @@ protected: sigc::connection lumaneutralPressedConn; sigc::connection lumacontrastPlusPressedConn; sigc::connection lumacontrastMinusPressedConn; + sigc::connection cbdlMethodConn; + Gtk::Label* labmcd; + Gtk::HBox* cdbox; + MyComboBoxText* cbdlMethod; bool lastgamutlab; @@ -61,7 +65,7 @@ public: void trimValues (rtengine::procparams::ProcParams* pp); void adjusterChanged (ThresholdAdjuster* a, int newBottomLeft, int newTopLeft, int newBottomRight, int newTopRight); // void algoChanged (); - + void cbdlMethodChanged(); void adjusterChanged (Adjuster* a, double newval); void enabledChanged(); void gamutlabToggled (); diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 7b29af12c..dab0e1e61 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -18,18 +18,20 @@ * along with RawTherapee. If not, see . */ #include "editorpanel.h" -#include "options.h" -#include "progressconnector.h" -#include "rtwindow.h" -#include "guiutils.h" -#include "procparamchangers.h" -#include "../rtengine/safegtk.h" + +#include + #include "../rtengine/imagesource.h" #include "../rtengine/iccstore.h" #include "soundman.h" #include "rtimage.h" -#include +#include "rtwindow.h" +#include "guiutils.h" #include "popupbutton.h" +#include "options.h" +#include "progressconnector.h" +#include "procparamchangers.h" +#include "placesbrowser.h" using namespace rtengine::procparams; @@ -516,7 +518,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) show_all (); /* // save as dialog - if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) + if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) saveAsDialog = new SaveAsDialog (options.lastSaveAsPath); else saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir()); @@ -813,7 +815,7 @@ void EditorPanel::close () navigator->previewWindow->setPreviewHandler (NULL); // If the file was deleted somewhere, the openThm.descreaseRef delete the object, but we don't know here - if (safe_file_test (fname, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { openThm->removeThumbnailListener (this); openThm->decreaseRef (); } @@ -827,7 +829,7 @@ void EditorPanel::saveProfile () } // If the file was deleted, do not generate ghost entries - if (safe_file_test (fname, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { ProcParams params; ipc->getParams (¶ms); @@ -1573,10 +1575,10 @@ void EditorPanel::saveAsPressed () SaveAsDialog* saveAsDialog; auto toplevel = static_cast (get_toplevel ()); - if (safe_file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR)) { saveAsDialog = new SaveAsDialog (options.lastSaveAsPath, toplevel); } else { - saveAsDialog = new SaveAsDialog (safe_get_user_picture_dir(), toplevel); + saveAsDialog = new SaveAsDialog (PlacesBrowser::userPicturesDir (), toplevel); } saveAsDialog->set_default_size (options.saveAsDialogWidth, options.saveAsDialogHeight); @@ -1620,7 +1622,7 @@ void EditorPanel::saveAsPressed () fnameTemp = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, dstext); } - if (!safe_file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { + if (!Glib::file_test (fnameTemp, Glib::FILE_TEST_EXISTS)) { fnameOut = fnameTemp; fnameOK = true; break; @@ -1731,10 +1733,11 @@ bool EditorPanel::idle_sendToGimp ( ProgressConnector *pc, Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format); + // TODO: Just list all file with a suitable name instead of brute force... int tries = 1; - while (safe_file_test (fileName, Glib::FILE_TEST_EXISTS) && tries < 1000) { - fileName = Glib::ustring::compose ("%1-%2.%3", fname, tries, sf.format); + while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries < 1000) { + fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format); tries++; } @@ -1770,99 +1773,21 @@ bool EditorPanel::idle_sentToGimp (ProgressConnector *pc, rtengine::IImage1 parent->setProgressStr (""); parent->setProgress (0.); bool success = false; - Glib::ustring cmdLine; - Glib::ustring executable; - // start gimp if (options.editorToSendTo == 1) { -#ifdef WIN32 - executable = Glib::build_filename (Glib::build_filename (options.gimpDir, "bin"), "gimp-win-remote"); - cmdLine = Glib::ustring ("\"") + executable + Glib::ustring ("\" gimp-2.4.exe ") + Glib::ustring ("\"") + filename + Glib::ustring ("\""); - - if ( safe_file_test (executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) { - success = safe_spawn_command_line_async (cmdLine); - } - -#elif defined __APPLE__ - cmdLine = Glib::ustring ("open -a /Applications/GIMP.app \'") + filename + Glib::ustring ("\'"); - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#else - cmdLine = Glib::ustring ("gimp \"") + filename + Glib::ustring ("\""); - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#endif - - if (!success) { -#ifdef WIN32 - int ver = 12; - - while (!success && ver) { - executable = Glib::build_filename (Glib::build_filename (options.gimpDir, "bin"), Glib::ustring::compose (Glib::ustring ("gimp-2.%1.exe"), ver)); - - if ( safe_file_test (executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) { - cmdLine = Glib::ustring ("\"") + executable + Glib::ustring ("\" \"") + filename + Glib::ustring ("\""); - success = safe_spawn_command_line_async (cmdLine); - } - - ver--; - } - -#elif defined __APPLE__ - cmdLine = Glib::ustring ("open -a /Applications/Gimp.app/Contents/Resources/start \'") + filename + Glib::ustring ("\'"); - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#else - cmdLine = Glib::ustring ("gimp-remote \"") + filename + Glib::ustring ("\""); - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#endif - } + success = ExtProgStore::openInGimp (filename); } else if (options.editorToSendTo == 2) { -#ifdef WIN32 - executable = Glib::build_filename (options.psDir, "Photoshop.exe"); - - if ( safe_file_test (executable, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) { - cmdLine = Glib::ustring ("\"") + executable + Glib::ustring ("\" \"") + filename + Glib::ustring ("\""); - success = safe_spawn_command_line_async (cmdLine); - } - -#else -#ifdef __APPLE__ - cmdLine = Glib::ustring ("open -a \'") + Glib::build_filename (options.psDir, "Photoshop.app\' ") + Glib::ustring ("\'") + filename + Glib::ustring ("\'"); -#else - cmdLine = Glib::ustring ("\"") + Glib::build_filename (options.psDir, "Photoshop.exe") + Glib::ustring ("\" \"") + filename + Glib::ustring ("\""); -#endif - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#endif + success = ExtProgStore::openInPhotoshop (filename); } else if (options.editorToSendTo == 3) { -#ifdef WIN32 - - if ( safe_file_test (options.customEditorProg, (Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) ) { - cmdLine = Glib::ustring ("\"") + options.customEditorProg + Glib::ustring ("\" \"") + filename + Glib::ustring ("\""); - success = safe_spawn_command_line_async (cmdLine); - } - -#else -#ifdef __APPLE__ - cmdLine = options.customEditorProg + Glib::ustring (" \"") + filename + Glib::ustring ("\""); -#else - cmdLine = Glib::ustring ("\"") + options.customEditorProg + Glib::ustring ("\" \"") + filename + Glib::ustring ("\""); -#endif - success = safe_spawn_command_line_async (cmdLine); - std::cout << cmdLine << std::endl; -#endif + success = ExtProgStore::openInCustomEditor (filename); } if (!success) { - Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M ("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd->set_secondary_text (M ("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY")); - msgd->set_title (M ("MAIN_BUTTON_SENDTOEDITOR")); - msgd->run (); - delete msgd; + Gtk::MessageDialog msgd (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + msgd.set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY")); + msgd.set_title (M("MAIN_BUTTON_SENDTOEDITOR")); + msgd.run (); } - } return false; diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 1ea4298ce..76e9eebe0 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -17,7 +17,7 @@ * along with RawTherapee. If not, see . */ #include "exifpanel.h" -#include "../rtengine/safegtk.h" + #include "guiutils.h" #include "rtimage.h" @@ -46,9 +46,9 @@ ExifPanel::ExifPanel () : idata(NULL) exifTreeModel = Gtk::TreeStore::create(exifColumns); exifTree->set_model (exifTreeModel); - delicon = safe_create_from_file ("gtk-close.png"); - keepicon = safe_create_from_file ("gtk-apply.png"); - editicon = safe_create_from_file ("gtk-add.png"); + delicon = RTImage::createFromFile ("gtk-close.png"); + keepicon = RTImage::createFromFile ("gtk-apply.png"); + editicon = RTImage::createFromFile ("gtk-add.png"); Gtk::TreeView::Column *viewcol = Gtk::manage(new Gtk::TreeView::Column ("Field Name")); Gtk::CellRendererPixbuf* render_pb = Gtk::manage(new Gtk::CellRendererPixbuf ()); diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc index b6ef31255..4f0018ab9 100644 --- a/rtgui/extprog.cc +++ b/rtgui/extprog.cc @@ -16,183 +16,317 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include - #include "extprog.h" -#include "multilangmgr.h" -#include "../rtengine/safegtk.h" + +#include +#include + #ifdef WIN32 #include -// for GCC32 -#ifndef _WIN32_IE -#define _WIN32_IE 0x0600 -#endif #include #endif -using namespace std; +#include "options.h" +#include "multilangmgr.h" -ExtProgAction::ExtProgAction() {} - -ExtProgAction::ExtProgAction(const ExtProgAction* other, int target) - : target(target), filePathEXE(other->filePathEXE), preparams(other->preparams), name(other->name) { } - -Glib::ustring ExtProgAction::GetFullName() +Glib::ustring ExtProgAction::getFullName () const { return name + " [" + M(Glib::ustring::compose("EXTPROGTARGET_%1", target)) + "]"; } -bool ExtProgAction::Execute(std::vector fileNames) +bool ExtProgAction::execute (const std::vector& fileNames) const { - if (fileNames.empty()) { + if (fileNames.empty ()) { return false; } - // Check if they all exists (maybe not precessed yet) - for (int i = 0; i < fileNames.size(); i++) { - if (!safe_file_test(fileNames[i], Glib::FILE_TEST_EXISTS)) { - Gtk::MessageDialog msgd (M("MAIN_MSG_IMAGEUNPROCESSED"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - msgd.run (); - return false; + // Check if they all exists as they may not be processed yet. + for (const auto& fileName : fileNames) { + + if (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS)) { + continue; } + + Gtk::MessageDialog (M("MAIN_MSG_IMAGEUNPROCESSED"), true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true).run (); + return false; } Glib::ustring cmdLine = "\"" + filePathEXE + "\""; - if (preparams.length() > 0) { + if (!preparams.empty()) { cmdLine += " " + preparams; } - for (int i = 0; i < fileNames.size(); i++) { - cmdLine += " \"" + fileNames[i] + "\""; + for (const auto& fileName : fileNames) { + cmdLine += " \"" + fileName + "\""; } - return safe_spawn_command_line_async (cmdLine); + return ExtProgStore::spawnCommandAsync (cmdLine); } - -// Generates as singleton ExtProgStore* ExtProgStore::getInstance() { static ExtProgStore instance_; return &instance_; } -ExtProgStore::~ExtProgStore() -{ - for (list::iterator it = lActions.begin(); it != lActions.end(); it++) { - delete *it; - } -} - // Reads all profiles from the given profiles dir void ExtProgStore::init () { MyMutex::MyLock lock(mtx); - lActions.clear(); + actions.clear (); #ifdef WIN32 - SearchProg("Photoshop", "Adobe\\Adobe Photoshop CS%1 (64 Bit)\\Photoshop.exe", "Adobe\\Adobe Photoshop CS%1\\Photoshop.exe", 9, false, true); - SearchProg("Photomatix Pro", "PhotomatixPro%1\\PhotomatixPro.exe", "", 9, true, true); - SearchProg("Paint.NET", "Paint.NET\\PaintDotNet.exe", "", 0, false, true); - SearchProg("MS Image Composition Editor", "Microsoft Research\\Image Composite Editor\\ICE.exe", "", 0, false, true); - SearchProg("PTGui", "PTGui\\PTGui.exe", "", 0, false, true); - SearchProg("GeoSetter", "GeoSetter\\GeoSetter.exe", "", 0, true, true); - SearchProg("FastStone Image Viewer", "FastStone Image Viewer\\FSViewer.exe", "", 0, true, true); - SearchProg("FastPictureViewer", "FastPictureViewer\\FastPictureViewer.exe", "", 0, true, true); + // Please do not add obscure little tools here, only widely used programs. + // They should also have a proper setup program and therefore a standard path. - if (!SearchProg("Autopano Giga 3", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga.exe", 15, true, true)) { - if ( !SearchProg("Autopano Pro 3", "Kolor\\Autopano Pro 3.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 3.%1\\AutopanoPro.exe", 15, true, true)) { - if (!SearchProg("Autopano Giga 2", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga.exe", 6, true, true)) { - SearchProg("Autopano Pro 2", "Kolor\\Autopano Pro 2.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 2.%1\\AutopanoPro.exe", 6, true, true); + searchProgram ("Photoshop", "Adobe\\Adobe Photoshop CS%1 (64 Bit)\\Photoshop.exe", "Adobe\\Adobe Photoshop CS%1\\Photoshop.exe", 9, false, true); + searchProgram ("Photomatix Pro", "PhotomatixPro%1\\PhotomatixPro.exe", "", 9, true, true); + searchProgram ("Paint.NET", "Paint.NET\\PaintDotNet.exe", "", 0, false, true); + searchProgram ("MS Image Composition Editor", "Microsoft Research\\Image Composite Editor\\ICE.exe", "", 0, false, true); + searchProgram ("PTGui", "PTGui\\PTGui.exe", "", 0, false, true); + searchProgram ("GeoSetter", "GeoSetter\\GeoSetter.exe", "", 0, true, true); + searchProgram ("FastStone Image Viewer", "FastStone Image Viewer\\FSViewer.exe", "", 0, true, true); + searchProgram ("FastPictureViewer", "FastPictureViewer\\FastPictureViewer.exe", "", 0, true, true); + + if (!searchProgram ("Autopano Giga 3", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 3.%1\\AutopanoGiga.exe", 15, true, true)) { + if (!searchProgram ("Autopano Pro 3", "Kolor\\Autopano Pro 3.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 3.%1\\AutopanoPro.exe", 15, true, true)) { + if (!searchProgram ("Autopano Giga 2", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga_x64.exe", "Kolor\\Autopano Giga 2.%1\\AutopanoGiga.exe", 6, true, true)) { + searchProgram ("Autopano Pro 2", "Kolor\\Autopano Pro 2.%1\\AutopanoPro_x64.exe", "Kolor\\Autopano Pro 2.%1\\AutopanoPro.exe", 6, true, true); } } } - // DO NOT add obscure little tools here, only widely used programs with proper setup program to have a standard path #endif } -bool ExtProgStore::SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess) +bool ExtProgStore::searchProgram (const Glib::ustring& name, + const Glib::ustring& exePath, + const Glib::ustring& exePath86, + int maxVer, + bool allowRaw, + bool allowQueueProcess) { - bool found = false; #ifdef WIN32 // get_user_special_dir crashes on some Windows configurations. - // so we use the safe native functions here static Glib::ustring progFilesDir, progFilesDirx86; - if (progFilesDir.empty()) { - WCHAR pathW[MAX_PATH] = {0}; + if (progFilesDir.empty ()) { + WCHAR pathW[MAX_PATH]; char pathA[MAX_PATH]; - // First prio folder (64bit, otherwise 32bit) - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PROGRAM_FILES, false)) { - char pathA[MAX_PATH]; - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - progFilesDir = Glib::ustring(pathA); + if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_PROGRAM_FILES, false)) { + if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) { + progFilesDir = pathA; + } } - if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_PROGRAM_FILESX86, false)) { - WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); - progFilesDirx86 = Glib::ustring(pathA); + if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_PROGRAM_FILESX86, false)) { + if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) { + progFilesDirx86 = pathA; + } } } - if (exePath86.empty()) { - exePath86 = exePath; - } + ExtProgAction action; + action.name = name; + action.target = (allowRaw ? 1 : 2); - ExtProgAction *pAct = new ExtProgAction(); - pAct->name = name; - pAct->target = (allowRaw ? 1 : 2); + auto& filePath = action.filePathEXE; if (maxVer > 0) { - for (int verNo = maxVer; verNo >= 0; verNo--) { - pAct->filePathEXE = progFilesDir + "\\" + Glib::ustring::compose(exePath, verNo); - if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { + for (auto ver = maxVer; ver >= 0; ver--) { + + filePath = progFilesDir + "\\" + Glib::ustring::compose(exePath, ver); + + if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { break; } - pAct->filePathEXE = progFilesDirx86 + "\\" + Glib::ustring::compose(exePath86, verNo); + if (!exePath86.empty ()) { - if (safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { - break; + filePath = progFilesDirx86 + "\\" + Glib::ustring::compose(exePath86, ver); + + if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + break; + } } - pAct->filePathEXE = ""; + filePath.clear (); } } else { - pAct->filePathEXE = progFilesDir + "\\" + exePath; - if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { + do { - pAct->filePathEXE = progFilesDirx86 + "\\" + exePath86; + filePath = progFilesDir + "\\" + exePath; - if (!safe_file_test(pAct->filePathEXE, Glib::FILE_TEST_EXISTS)) { - pAct->filePathEXE = ""; + if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + break; } - } + + if (!exePath86.empty ()) { + + filePath = progFilesDirx86 + "\\" + exePath86; + + if (Glib::file_test (filePath, Glib::FILE_TEST_EXISTS)) { + break; + } + } + + filePath.clear (); + + } while (false); } - if (pAct->filePathEXE.length() > 0) { - lActions.push_back(pAct); + if (!action.filePathEXE.empty ()) { + + actions.push_back (action); - // Copy for second target if (allowRaw && allowQueueProcess) { - lActions.push_back(new ExtProgAction(pAct, 2)); + + action.target = 2; + actions.push_back (action); } - found = true; - } else { - delete pAct; + return true; } #endif - return found; + return false; +} + +bool ExtProgStore::spawnCommandAsync (const Glib::ustring& cmd) +{ + try { + + const auto encodedCmd = Glib::filename_from_utf8 (cmd); + Glib::spawn_command_line_async (encodedCmd.c_str ()); + + return true; + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to execute \"" << cmd << "\": " << exception.what() << std::endl; + } + + return false; + + } +} + +bool ExtProgStore::spawnCommandSync (const Glib::ustring& cmd) +{ + auto exitStatus = -1; + + try { + + Glib::spawn_command_line_sync (cmd, NULL, NULL, &exitStatus); + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to execute \"" << cmd << "\": " << exception.what() << std::endl; + } + + } + + return exitStatus == 0; +} + +bool ExtProgStore::openInGimp (const Glib::ustring& fileName) +{ +#if defined WIN32 + + auto executable = Glib::build_filename (options.gimpDir, "bin", "gimp-win-remote"); + auto cmdLine = Glib::ustring::compose ("\"%1\" gimp-2.4.exe \"%2\"", executable, fileName); + auto success = spawnCommandAsync (cmdLine); + +#elif defined __APPLE__ + + auto cmdLine = Glib::ustring("open -a /Applications/GIMP.app \'") + fileName + Glib::ustring("\'"); + auto success = spawnCommandAsync (cmdLine); + +#else + + auto cmdLine = Glib::ustring("gimp \"") + fileName + Glib::ustring("\""); + auto success = spawnCommandAsync (cmdLine); + +#endif + + if (success) { + return true; + } + +#ifdef WIN32 + + for (auto ver = 12; ver >= 0; --ver) { + + executable = Glib::build_filename (options.gimpDir, "bin", Glib::ustring::compose (Glib::ustring("gimp-2.%1.exe"), ver)); + cmdLine = Glib::ustring::compose ("\"%1\" \"%2\"", executable, fileName); + success = spawnCommandAsync (cmdLine); + + if (success) { + return true; + } + } + +#elif defined __APPLE__ + + cmdLine = Glib::ustring("open -a /Applications/Gimp.app/Contents/Resources/start \'") + fileName + Glib::ustring("\'"); + success = ExtProgStore::spawnCommandAsync (cmdLine); + +#else + + cmdLine = Glib::ustring("gimp-remote \"") + fileName + Glib::ustring("\""); + success = ExtProgStore::spawnCommandAsync (cmdLine); + +#endif + + return success; +} + +bool ExtProgStore::openInPhotoshop (const Glib::ustring& fileName) +{ +#if defined WIN32 + + const auto executable = Glib::build_filename(options.psDir, "Photoshop.exe"); + const auto cmdLine = Glib::ustring("\"") + executable + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + +#elif defined __APPLE__ + + const auto cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir, "Photoshop.app\' ") + Glib::ustring("\'") + fileName + Glib::ustring("\'"); + +#else + + const auto cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir, "Photoshop.exe") + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + +#endif + + return spawnCommandAsync (cmdLine); +} + +bool ExtProgStore::openInCustomEditor (const Glib::ustring& fileName) +{ +#if defined WIN32 + + const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + +#elif defined __APPLE__ + + const auto cmdLine = options.customEditorProg + Glib::ustring(" \"") + fileName + Glib::ustring("\""); + +#else + + const auto cmdLine = Glib::ustring("\"") + options.customEditorProg + Glib::ustring("\" \"") + fileName + Glib::ustring("\""); + +#endif + + return spawnCommandAsync (cmdLine); } diff --git a/rtgui/extprog.h b/rtgui/extprog.h index 2069bc8e8..fe7375ce7 100644 --- a/rtgui/extprog.h +++ b/rtgui/extprog.h @@ -20,42 +20,58 @@ #ifndef _EXTPROG_ #define _EXTPROG_ -#include -#include +#include + +#include + #include "threadutils.h" -class ExtProgAction +struct ExtProgAction { -public: - ExtProgAction(); - ExtProgAction(const ExtProgAction* other, int target); - Glib::ustring filePathEXE; Glib::ustring preparams; // after EXE and before file names Glib::ustring name; // already localized if necessary int target; // 1=RAW files, 2=batch converted files - Glib::ustring GetFullName(); // e.g. "Photoshop (RAW)" + Glib::ustring getFullName () const; // e.g. "Photoshop (RAW)" - virtual bool Execute(std::vector fileNames); + bool execute (const std::vector& fileNames) const; }; // Stores all external programs that could be called by the user class ExtProgStore { MyMutex mtx; // covers actions + std::vector actions; - bool SearchProg(Glib::ustring name, Glib::ustring exePath, Glib::ustring exePath86, int maxVer, bool allowRaw, bool allowQueueProcess); + bool searchProgram (const Glib::ustring& name, + const Glib::ustring& exePath, + const Glib::ustring& exePath86, + int maxVer, + bool allowRaw, + bool allowQueueProcess); public: - ~ExtProgStore(); - - void init(); // searches computer for installed standard programs static ExtProgStore* getInstance(); - std::list lActions; + // searches computer for installed standard programs + void init(); + + const std::vector& getActions () const; + + static bool spawnCommandAsync (const Glib::ustring& cmd); + static bool spawnCommandSync (const Glib::ustring& cmd); + + static bool openInGimp (const Glib::ustring& fileName); + static bool openInPhotoshop (const Glib::ustring& fileName); + static bool openInCustomEditor (const Glib::ustring& fileName); }; #define extProgStore ExtProgStore::getInstance() +inline const std::vector& ExtProgStore::getActions () const +{ + return actions; +} + #endif diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index 6aacc76a5..3b0a89d6f 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -224,11 +224,9 @@ FileBrowser::FileBrowser () mMenuExtProgs.clear(); amiExtProg = NULL; - for (std::list::iterator it = extProgStore->lActions.begin(); it != extProgStore->lActions.end(); it++) { - ExtProgAction* pAct = *it; - - if (pAct->target == 1 || pAct->target == 2) { - mMenuExtProgs[pAct->GetFullName()] = pAct; + for (const auto& action : extProgStore->getActions ()) { + if (action.target == 1 || action.target == 2) { + mMenuExtProgs[action.getFullName ()] = &action; } } @@ -247,7 +245,7 @@ FileBrowser::FileBrowser () p++; } - for (std::map::iterator it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) { + for (auto it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) { submenuExtProg->attach (*Gtk::manage(amiExtProg[itemNo] = new Gtk::MenuItem ((*it).first)), 0, 1, p, p + 1); p++; } @@ -260,7 +258,7 @@ FileBrowser::FileBrowser () p++; } - for (std::map::iterator it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) { + for (auto it = mMenuExtProgs.begin(); it != mMenuExtProgs.end(); it++, itemNo++) { pmenu->attach (*Gtk::manage(amiExtProg[itemNo] = new Gtk::MenuItem ((*it).first)), 0, 1, p, p + 1); p++; } @@ -736,7 +734,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) for (int j = 0; j < mMenuExtProgs.size(); j++) { if (m == amiExtProg[j]) { - ExtProgAction* pAct = mMenuExtProgs[m->get_label()]; + const auto pAct = mMenuExtProgs[m->get_label()]; // Build vector of all file names std::vector selFileNames; @@ -752,7 +750,7 @@ void FileBrowser::menuItemActivated (Gtk::MenuItem* m) selFileNames.push_back(fn); } - pAct->Execute(selFileNames); + pAct->execute (selFileNames); return; } } diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h index cdb9b133f..fdb08ba24 100644 --- a/rtgui/filebrowser.h +++ b/rtgui/filebrowser.h @@ -93,7 +93,7 @@ protected: Gtk::MenuItem* menuExtProg; Gtk::MenuItem** amiExtProg; Gtk::MenuItem* miOpenDefaultViewer; - std::map mMenuExtProgs; // key is menuitem label + std::map mMenuExtProgs; // key is menuitem label Gtk::MenuItem* menuDF; Gtk::MenuItem* selectDF; diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index 97368dbb4..bcbac7746 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -17,16 +17,17 @@ * along with RawTherapee. If not, see . */ #include "filebrowserentry.h" -#include "thumbbrowserbase.h" -#include "cursormanager.h" + #include +#include + #include "guiutils.h" #include "threadutils.h" -#include "../rtengine/safegtk.h" +#include "rtimage.h" +#include "cursormanager.h" +#include "thumbbrowserbase.h" #include "inspector.h" -#include - #define CROPRESIZEBORDER 4 //extern Glib::Threads::Thread* mainThread; @@ -53,9 +54,9 @@ FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) scale = 1; if (!iconsLoaded) { - editedIcon = safe_create_from_file ("edited.png"); - recentlySavedIcon = safe_create_from_file ("recent-save.png"); - enqueuedIcon = safe_create_from_file ("processing.png"); + editedIcon = RTImage::createFromFile ("edited.png"); + recentlySavedIcon = RTImage::createFromFile ("recent-save.png"); + enqueuedIcon = RTImage::createFromFile ("processing.png"); iconsLoaded = true; } diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 6f7578f02..4fa954d15 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -17,22 +17,25 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include +#include "filecatalog.h" + #include #include + +#include + #include "../rtengine/rt_math.h" -#include "filecatalog.h" -#include "filepanel.h" +#include "guiutils.h" #include "options.h" +#include "rtimage.h" #include "cachemanager.h" #include "multilangmgr.h" -#include "guiutils.h" +#include "filepanel.h" #include "renamedlg.h" #include "thumbimageupdater.h" -#include "../rtengine/safegtk.h" #include "batchqueue.h" -#include "rtimage.h" +#include "placesbrowser.h" using namespace std; @@ -544,11 +547,44 @@ void FileCatalog::closeDir () std::vector FileCatalog::getFileList () { - std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path (selectedDirectory); - safe_build_file_list (dir, names, selectedDirectory, &(options.parsedExtensions)); -// Issue 2406 std::sort (names.begin(), names.end()); + + std::set extensions; + for (const auto& parsedExt : options.parsedExtensions) { + extensions.emplace (parsedExt.lowercase ()); + } + + try { + + auto dir = Gio::File::create_for_path (selectedDirectory); + + auto enumerator = dir->enumerate_children ("standard::name"); + + while (auto file = enumerator->next_file ()) { + + const Glib::ustring fname = file->get_name (); + + auto lastdot = fname.find_last_of ('.'); + if (lastdot >= fname.length () - 1) { + continue; + } + + const auto fext = fname.substr (lastdot + 1).lowercase (); + if (extensions.count (fext) == 0) { + continue; + } + + names.emplace_back (Glib::build_filename (selectedDirectory, fname)); + } + + } catch (Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to list directory \"" << selectedDirectory << "\": " << exception.what() << std::endl; + } + + } + return names; } @@ -908,35 +944,26 @@ void FileCatalog::deleteRequested (std::vector tbe, bool inc if (msd.run() == Gtk::RESPONSE_YES) { for (unsigned int i = 0; i < tbe.size(); i++) { - Glib::ustring fname = tbe[i]->filename; + const auto fname = tbe[i]->filename; // remove from browser - FileBrowserEntry* t = fileBrowser->delEntry (fname); -// t->thumbnail->decreaseRef (); - delete t; + delete fileBrowser->delEntry (fname); // remove from cache cacheMgr->deleteEntry (fname); // delete from file system - safe_g_remove (fname); + ::g_remove (fname.c_str ()); // delete paramfile if found - safe_g_remove (Glib::ustring(fname + paramFileExtension)); - safe_g_remove (Glib::ustring(removeExtension(fname) + paramFileExtension)); + ::g_remove ((fname + paramFileExtension).c_str ()); + ::g_remove ((removeExtension(fname) + paramFileExtension).c_str ()); // delete .thm file - safe_g_remove (Glib::ustring(removeExtension(fname) + ".thm")); - safe_g_remove (Glib::ustring(removeExtension(fname) + ".THM")); + ::g_remove ((removeExtension(fname) + ".thm").c_str ()); + ::g_remove ((removeExtension(fname) + ".THM").c_str ()); if (inclBatchProcessed) { Glib::ustring procfName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); + ::g_remove (procfName.c_str ()); - if (safe_file_test (procfName, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (procfName); - } - - // delete paramfile if found Glib::ustring procfNameParamFile = Glib::ustring::compose ("%1.%2.out%3", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format, paramFileExtension); - - if (safe_file_test (procfNameParamFile, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (procfNameParamFile); - } + ::g_remove (procfNameParamFile.c_str ()); } previewsLoaded--; @@ -1007,7 +1034,7 @@ void FileCatalog::copyMoveRequested (std::vector tbe, bool m while(!filecopymovecomplete) { // check for filename conflicts at destination - prevent overwriting (actually RT will crash on overwriting attempt) - if (!safe_file_test(dest_fPath, Glib::FILE_TEST_EXISTS) && !safe_file_test(dest_fPath_param, Glib::FILE_TEST_EXISTS)) { + if (!Glib::file_test(dest_fPath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(dest_fPath_param, Glib::FILE_TEST_EXISTS)) { // copy/move file to destination Glib::RefPtr dest_file = Gio::File::create_for_path ( dest_fPath ); @@ -1028,15 +1055,15 @@ void FileCatalog::copyMoveRequested (std::vector tbe, bool m // attempt to copy/move paramFile only if it exist next to the src Glib::RefPtr scr_param = Gio::File::create_for_path ( src_fPath + paramFileExtension ); - if (safe_file_test( src_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test( src_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { Glib::RefPtr dest_param = Gio::File::create_for_path ( dest_fPath_param); // copy/move paramFile to destination if (moveRequested) { - if (safe_file_test( dest_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test( dest_fPath + paramFileExtension, Glib::FILE_TEST_EXISTS)) { // profile already got copied to destination from cache after cacheMgr->renameEntry // delete source profile as cleanup - safe_g_remove (src_fPath + paramFileExtension); + ::g_remove ((src_fPath + paramFileExtension).c_str ()); } else { scr_param->move(dest_param); } @@ -1238,16 +1265,16 @@ void FileCatalog::renameRequested (std::vector tbe) Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); /* check if filename already exists*/ - if (safe_file_test (nfname, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (nfname, Glib::FILE_TEST_EXISTS)) { Glib::ustring msg_ = Glib::ustring("") + nfname + ": " + M("MAIN_MSG_ALREADYEXISTS") + ""; Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); msgd.run (); } else { success = true; - if (!safe_g_rename (ofname, nfname)) { + if (::g_rename (ofname.c_str (), nfname.c_str ()) == 0) { cacheMgr->renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname); - safe_g_remove(ofname + paramFileExtension); + ::g_remove((ofname + paramFileExtension).c_str ()); reparseDirectory (); } } @@ -1684,7 +1711,7 @@ void FileCatalog::reparseDirectory () return; } - if (!safe_file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { + if (!Glib::file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { closeDir (); return; } @@ -1696,7 +1723,7 @@ void FileCatalog::reparseDirectory () std::vector fileNamesToDel; for (size_t i = 0; i < t.size(); i++) - if (!safe_file_test (t[i]->filename, Glib::FILE_TEST_EXISTS)) { + if (!Glib::file_test (t[i]->filename, Glib::FILE_TEST_EXISTS)) { fileNamesToDel.push_back (t[i]->filename); } @@ -1761,63 +1788,91 @@ void FileCatalog::on_dir_changed (const Glib::RefPtr& file, const Gli void FileCatalog::checkAndAddFile (Glib::RefPtr file) { - - if (!file ) { + if (!file) { return; } - if( !file->query_exists()) { + if (!file->query_exists()) { return; } - Glib::RefPtr info = safe_query_file_info(file); + try { - if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) { - size_t lastdot = info->get_name().find_last_of ('.'); + auto info = file->query_info (); - if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { - previewLoader->add (selectedDirectoryId, file->get_parse_name(), this); - previewsToLoad++; + if (!info || info->get_file_type () == Gio::FILE_TYPE_DIRECTORY) { + return; } - } + + if (!options.fbShowHidden && info->is_hidden ()) { + return; + } + + Glib::ustring ext; + + const auto lastdot = info->get_name ().find_last_of ('.'); + if (lastdot != Glib::ustring::npos) { + ext = info->get_name ().substr (lastdot + 1); + } + + if (!options.is_extention_enabled (ext)) { + return; + } + + previewLoader->add (selectedDirectoryId, file->get_parse_name (), this); + previewsToLoad++; + + } catch(Gio::Error&) {} } void FileCatalog::addAndOpenFile (const Glib::ustring& fname) { - - Glib::RefPtr file = Gio::File::create_for_path (fname); + auto file = Gio::File::create_for_path (fname); if (!file ) { return; } - if( !file->query_exists()) { + if (!file->query_exists ()) { return; } - Glib::RefPtr info = safe_query_file_info(file); + try { - if( !info ) { - return; - } + auto info = file->query_info (); - size_t lastdot = info->get_name().find_last_of ('.'); - - if (options.is_extention_enabled(lastdot != Glib::ustring::npos ? info->get_name().substr (lastdot + 1) : "")) { - // if supported, load thumbnail first - Thumbnail* tmb = cacheMgr->getEntry (file->get_parse_name()); - - if (tmb) { - FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name()); - previewReady (selectedDirectoryId, entry); - // open the file - FCOIParams* params = new FCOIParams; - params->catalog = this; - params->tmb.push_back (tmb); - tmb->increaseRef (); - g_idle_add (openRequestedUI, params); + if (!info) { + return; } - } + + Glib::ustring ext; + + auto lastdot = info->get_name().find_last_of ('.'); + if (lastdot != Glib::ustring::npos) { + ext = info->get_name ().substr (lastdot + 1); + } + + if (!options.is_extention_enabled(ext)) { + return; + } + + // if supported, load thumbnail first + const auto tmb = cacheMgr->getEntry (file->get_parse_name ()); + + if (!tmb) { + return; + } + + FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name ()); + previewReady (selectedDirectoryId, entry); + // open the file + FCOIParams* params = new FCOIParams; + params->catalog = this; + params->tmb.push_back (tmb); + tmb->increaseRef (); + g_idle_add (openRequestedUI, params); + + } catch(Gio::Error&) {} } void FileCatalog::emptyTrash () @@ -1989,10 +2044,9 @@ void FileCatalog::buttonBrowsePathPressed () FirstChar = BrowsePathValue.substr (0, 1); if (FirstChar == "~") { // home directory - DecodedPathPrefix = Glib::get_home_dir(); + DecodedPathPrefix = PlacesBrowser::userHomeDir (); } else if (FirstChar == "!") { // user's pictures directory - //DecodedPathPrefix = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES); - DecodedPathPrefix = safe_get_user_picture_dir(); + DecodedPathPrefix = PlacesBrowser::userPicturesDir (); } if (!DecodedPathPrefix.empty()) { @@ -2003,7 +2057,7 @@ void FileCatalog::buttonBrowsePathPressed () // handle shortcuts in the BrowsePath -- END // validate the path - if (safe_file_test(BrowsePathValue, Glib::FILE_TEST_IS_DIR) && selectDir) { + if (Glib::file_test(BrowsePathValue, Glib::FILE_TEST_IS_DIR) && selectDir) { selectDir (BrowsePathValue); } else // error, likely path not found: show red arrow diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index af3a61c21..6819890e5 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -1,4 +1,3 @@ - /* * This file is part of RawTherapee. * @@ -18,9 +17,10 @@ * along with RawTherapee. If not, see . */ #include "filepanel.h" + #include "rtwindow.h" -#include "../rtengine/safegtk.h" #include "inspector.h" +#include "placesbrowser.h" int FilePanelInitUI (void* data) { @@ -188,19 +188,19 @@ void FilePanel::init () dirBrowser->fillDirTree (); placesBrowser->refreshPlacesList (); - if (argv1 != "" && safe_file_test (argv1, Glib::FILE_TEST_IS_DIR)) { + if (argv1 != "" && Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { dirBrowser->open (argv1); } else { if (options.startupDir == STARTUPDIR_HOME) { - dirBrowser->open (safe_get_user_picture_dir()); + dirBrowser->open (PlacesBrowser::userPicturesDir ()); } else if (options.startupDir == STARTUPDIR_CURRENT) { dirBrowser->open (argv0); } else if (options.startupDir == STARTUPDIR_CUSTOM || options.startupDir == STARTUPDIR_LAST) { - if (options.startupPath.length() && safe_file_test(options.startupPath, Glib::FILE_TEST_EXISTS) && safe_file_test(options.startupPath, Glib::FILE_TEST_IS_DIR)) { + if (options.startupPath.length() && Glib::file_test(options.startupPath, Glib::FILE_TEST_EXISTS) && Glib::file_test(options.startupPath, Glib::FILE_TEST_IS_DIR)) { dirBrowser->open (options.startupPath); } else { // Fallback option if the path is empty or the folder doesn't exist - dirBrowser->open (safe_get_user_picture_dir()); + dirBrowser->open (PlacesBrowser::userPicturesDir ()); } } } @@ -333,9 +333,9 @@ void FilePanel::saveOptions () void FilePanel::open (const Glib::ustring& d) { - if (safe_file_test (d, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (d, Glib::FILE_TEST_IS_DIR)) { dirBrowser->open (d.c_str()); - } else if (safe_file_test (d, Glib::FILE_TEST_EXISTS)) { + } else if (Glib::file_test (d, Glib::FILE_TEST_EXISTS)) { dirBrowser->open (Glib::path_get_dirname(d), Glib::path_get_basename(d)); } } diff --git a/rtgui/filethumbnailbuttonset.cc b/rtgui/filethumbnailbuttonset.cc index e9970b177..286324bdf 100644 --- a/rtgui/filethumbnailbuttonset.cc +++ b/rtgui/filethumbnailbuttonset.cc @@ -17,8 +17,9 @@ * along with RawTherapee. If not, see . */ #include "filethumbnailbuttonset.h" + +#include "rtimage.h" #include "multilangmgr.h" -#include "../rtengine/safegtk.h" extern Glib::ustring argv0; @@ -41,19 +42,19 @@ FileThumbnailButtonSet::FileThumbnailButtonSet (FileBrowserEntry* myEntry) { if (!iconsLoaded) { - unRankIcon = safe_create_from_png ("ratednotg.png"); - rankIcon = safe_create_from_png ("rated.png"); - gRankIcon = safe_create_from_png ("grayrated.png"); - trashIcon = safe_create_from_png ("trash-thumbnail.png"); - unTrashIcon = safe_create_from_png ("undelete-thumbnail.png"); - processIcon = safe_create_from_png ("processing-thumbnail.png"); + unRankIcon = RTImage::createFromPng ("ratednotg.png"); + rankIcon = RTImage::createFromPng ("rated.png"); + gRankIcon = RTImage::createFromPng ("grayrated.png"); + trashIcon = RTImage::createFromPng ("trash-thumbnail.png"); + unTrashIcon = RTImage::createFromPng ("undelete-thumbnail.png"); + processIcon = RTImage::createFromPng ("processing-thumbnail.png"); - colorLabelIcon_0 = safe_create_from_png ("cglabel0.png"); //("nocolorlabel.png"); - colorLabelIcon_1 = safe_create_from_png ("clabel1.png"); - colorLabelIcon_2 = safe_create_from_png ("clabel2.png"); - colorLabelIcon_3 = safe_create_from_png ("clabel3.png"); - colorLabelIcon_4 = safe_create_from_png ("clabel4.png"); - colorLabelIcon_5 = safe_create_from_png ("clabel5.png"); + colorLabelIcon_0 = RTImage::createFromPng ("cglabel0.png"); //("nocolorlabel.png"); + colorLabelIcon_1 = RTImage::createFromPng ("clabel1.png"); + colorLabelIcon_2 = RTImage::createFromPng ("clabel2.png"); + colorLabelIcon_3 = RTImage::createFromPng ("clabel3.png"); + colorLabelIcon_4 = RTImage::createFromPng ("clabel4.png"); + colorLabelIcon_5 = RTImage::createFromPng ("clabel5.png"); iconsLoaded = true; } diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc index 93abe18fb..07f85df94 100644 --- a/rtgui/filmsimulation.cc +++ b/rtgui/filmsimulation.cc @@ -4,7 +4,6 @@ #include "options.h" #include "../rtengine/clutstore.h" -#include "../rtengine/safegtk.h" using namespace rtengine; using namespace rtengine::procparams; diff --git a/rtgui/flatfield.cc b/rtgui/flatfield.cc index d12381b90..aec6820a5 100644 --- a/rtgui/flatfield.cc +++ b/rtgui/flatfield.cc @@ -19,7 +19,6 @@ #include "flatfield.h" #include "options.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include "rtimage.h" @@ -140,7 +139,7 @@ void FlatField::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi } } - if (safe_file_test (pp->raw.ff_file, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (pp->raw.ff_file, Glib::FILE_TEST_EXISTS)) { flatFieldFile->set_filename (pp->raw.ff_file); } else { flatFieldFile_Reset(); @@ -392,28 +391,21 @@ void FlatField::flatFieldAutoSelectChanged() } -void FlatField::setShortcutPath(Glib::ustring path) +void FlatField::setShortcutPath(const Glib::ustring& path) { - if (path == "") { + if (path.empty ()) { return; } -#ifdef WIN32 + try { - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(path)) -#endif - { - if (lastShortcutPath != "") { - try { - flatFieldFile->remove_shortcut_folder(lastShortcutPath); - } catch (Glib::Error &err) {} + if (!lastShortcutPath.empty ()) { + flatFieldFile->remove_shortcut_folder (lastShortcutPath); } + flatFieldFile->add_shortcut_folder (path); + lastShortcutPath = path; - try { - flatFieldFile->add_shortcut_folder(path); - } catch (Glib::Error &err) {} - } + } catch (Glib::Error&) {} } diff --git a/rtgui/flatfield.h b/rtgui/flatfield.h index 162360b9a..b85b154da 100644 --- a/rtgui/flatfield.h +++ b/rtgui/flatfield.h @@ -75,7 +75,7 @@ public: void flatFieldFile_Reset (); void flatFieldAutoSelectChanged (); void flatFieldBlurTypeChanged (); - void setShortcutPath(Glib::ustring path); + void setShortcutPath (const Glib::ustring& path); void setFFProvider (FFProvider* p) { ffp = p; diff --git a/rtgui/gradient.cc b/rtgui/gradient.cc index 93011f55b..7492d456b 100644 --- a/rtgui/gradient.cc +++ b/rtgui/gradient.cc @@ -156,29 +156,24 @@ void Gradient::updateGeometry(const int centerX, const int centerY, const double } } - PolarCoord polCoord1, polCoord2; - double decay = feather * rtengine::norm2(imW, imH) / 200.; - - rtengine::Coord origin(imW / 2 + centerX * imW / 200, imH / 2 + centerY * imH / 200); - - Line *currLine; - Circle *currCircle; + const auto decay = feather * rtengine::norm2 (imW, imH) / 200.0; + rtengine::Coord origin (imW / 2 + centerX * imW / 200, imH / 2 + centerY * imH / 200); const auto updateLine = [&](Geometry* geometry, const float radius, const float begin, const float end) { const auto line = static_cast(geometry); - line->begin.setFromPolar(PolarCoord(radius, -degree + begin)); + line->begin = PolarCoord(radius, -degree + begin); line->begin += origin; - line->end.setFromPolar(PolarCoord(radius, -degree + end)); + line->end = PolarCoord(radius, -degree + end); line->end += origin; }; const auto updateLineWithDecay = [&](Geometry* geometry, const float radius, const float offSetAngle) { const auto line = static_cast(geometry); - line->begin.setFromPolar(PolarCoord(radius, -degree + 180.) + PolarCoord(decay, -degree + offSetAngle)); + line->begin = PolarCoord (radius, -degree + 180.) + PolarCoord (decay, -degree + offSetAngle); line->begin += origin; - line->end.setFromPolar(PolarCoord(radius, -degree) + PolarCoord(decay, -degree + offSetAngle)); + line->end = PolarCoord (radius, -degree) + PolarCoord (decay, -degree + offSetAngle); line->end += origin; }; @@ -408,7 +403,7 @@ bool Gradient::button1Pressed(int modifierKey) p1.y = p2.y; p2.y = p; - pCoord.setFromCartesian(p1, p2); + pCoord = p2 - p1; draggedPointOldAngle = pCoord.angle; //printf("\ndraggedPointOldAngle=%.3f\n\n", draggedPointOldAngle); draggedPointAdjusterAngle = degree->getValue(); @@ -427,7 +422,7 @@ bool Gradient::button1Pressed(int modifierKey) centerPos.y = currPos.y; currPos.y = p; - draggedPoint.setFromCartesian(centerPos, currPos); + draggedPoint = currPos - centerPos; // compute the projected value of the dragged point draggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*M_PI); @@ -485,7 +480,7 @@ bool Gradient::drag1(int modifierKey) centerPos.y = currPos.y; currPos.y = p; - draggedPoint.setFromCartesian(centerPos, currPos); + draggedPoint = currPos - centerPos; double deltaAngle = draggedPoint.angle - draggedPointOldAngle; if (deltaAngle > 180.) { // crossing the boundary (0->360) @@ -530,7 +525,7 @@ bool Gradient::drag1(int modifierKey) centerPos.y = currPos.y; currPos.y = p; - draggedPoint.setFromCartesian(centerPos, currPos); + draggedPoint = currPos - centerPos; double currDraggedFeatherOffset = draggedPoint.radius * sin((draggedPoint.angle - degree->getValue()) / 180.*M_PI); if (lastObject == 2) diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index f7a4db474..da47323aa 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -22,7 +22,6 @@ #include "options.h" #include "../rtengine/rt_math.h" #include "../rtengine/utils.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" #include "multilangmgr.h" @@ -202,7 +201,7 @@ bool confirmOverwrite (Gtk::Window& parent, const std::string& filename) { bool safe = true; - if (safe_file_test (filename, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (filename, Glib::FILE_TEST_EXISTS)) { Glib::ustring msg_ = Glib::ustring ("\"") + Glib::path_get_basename (filename) + "\": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE"); Gtk::MessageDialog msgd (parent, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index a82df41f6..a0ed10fb6 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -20,7 +20,6 @@ #include "icmpanel.h" #include "options.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "../rtengine/iccstore.h" #include "../rtengine/dcp.h" #include "rtimage.h" @@ -609,7 +608,7 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) } else if (icameraICC->get_active ()) { pp->icm.input = "(cameraICC)"; } else { - if (safe_file_test (ipDialog->get_filename (), Glib::FILE_TEST_EXISTS) && !safe_file_test (ipDialog->get_filename (), Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (ipDialog->get_filename (), Glib::FILE_TEST_EXISTS) && !Glib::file_test (ipDialog->get_filename (), Glib::FILE_TEST_IS_DIR)) { pp->icm.input = "file:" + ipDialog->get_filename (); } else { pp->icm.input = ""; // just a directory diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 397fc8b59..422e45441 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -22,14 +22,13 @@ #include "cursormanager.h" #include "guiutils.h" #include "options.h" -#include "../rtengine/safegtk.h" #include "../rtengine/previewimage.h" extern Options options; InspectorBuffer::InspectorBuffer(const Glib::ustring &imagePath) : currTransform(0), fromRaw(false) { - if (!imagePath.empty() && safe_file_test(imagePath, Glib::FILE_TEST_EXISTS) && !safe_file_test(imagePath, Glib::FILE_TEST_IS_DIR)) { + if (!imagePath.empty() && Glib::file_test(imagePath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(imagePath, Glib::FILE_TEST_IS_DIR)) { imgPath = imagePath; // generate thumbnail image diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index e062ad077..a7a634443 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -19,7 +19,6 @@ #include #include "lensprofile.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "../rtengine/lcp.h" #include #include "rtimage.h" diff --git a/rtgui/main.cc b/rtgui/main.cc index 3a7174d6a..5bf81caaa 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -54,8 +54,6 @@ #include "conio.h" #endif -#include "../rtengine/safegtk.h" - extern Options options; // stores path to data files @@ -69,6 +67,29 @@ Glib::RefPtr cssForced; Glib::RefPtr cssRT; //Glib::Threads::Thread* mainThread; +namespace +{ + +// For an unknown reason, Glib::filename_to_utf8 doesn't work on reliably Windows, +// so we're using Glib::filename_to_utf8 for Linux/Apple and Glib::locale_to_utf8 for Windows. +Glib::ustring fname_to_utf8 (const char* fname) +{ +#ifdef WIN32 + + try { + return Glib::locale_to_utf8 (fname); + } catch (Glib::Error&) { + return Glib::convert_with_fallback (fname, "UTF-8", "ISO-8859-1", "?"); + } + +#else + + return Glib::filename_to_utf8 (fname); + +#endif +} + +} // This recursive mutex will be used by gdk_threads_enter/leave instead of a simple mutex #ifdef WIN32 @@ -177,7 +198,7 @@ int main(int argc, char **argv) bool consoleOpened = false; if (argc > 1 || options.rtSettings.verbose) { - if(options.rtSettings.verbose || ( !safe_file_test( safe_filename_to_utf8(argv[1]), Glib::FILE_TEST_EXISTS ) && !safe_file_test( safe_filename_to_utf8(argv[1]), Glib::FILE_TEST_IS_DIR ))) { + if (options.rtSettings.verbose || ( !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_EXISTS ) && !Glib::file_test (fname_to_utf8 (argv[1]), Glib::FILE_TEST_IS_DIR))) { bool stdoutRedirectedtoFile = (GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) == 0x0001); bool stderrRedirectedtoFile = (GetFileType(GetStdHandle(STD_ERROR_HANDLE)) == 0x0001); @@ -270,8 +291,8 @@ int main(int argc, char **argv) #ifndef WIN32 // Move the old path to the new one if the new does not exist - if (safe_file_test(Glib::build_filename(options.rtdir, "cache"), Glib::FILE_TEST_IS_DIR) && !safe_file_test(options.cacheBaseDir, Glib::FILE_TEST_IS_DIR)) { - safe_g_rename(Glib::build_filename(options.rtdir, "cache"), options.cacheBaseDir); + if (Glib::file_test(Glib::build_filename(options.rtdir, "cache"), Glib::FILE_TEST_IS_DIR) && !Glib::file_test(options.cacheBaseDir, Glib::FILE_TEST_IS_DIR)) { + g_rename(Glib::build_filename (options.rtdir, "cache").c_str (), options.cacheBaseDir.c_str ()); } #endif @@ -279,7 +300,7 @@ int main(int argc, char **argv) simpleEditor = false; if( !argv1.empty() ) - if( safe_file_test(argv1, Glib::FILE_TEST_EXISTS) && !safe_file_test(argv1, Glib::FILE_TEST_IS_DIR)) { + if( Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) && !Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { simpleEditor = true; } @@ -421,9 +442,9 @@ int processLineParams( int argc, char **argv ) case 'o': // outputfile or dir if( iArg + 1 < argc ) { iArg++; - outputPath = safe_filename_to_utf8 (argv[iArg]); + outputPath = fname_to_utf8 (argv[iArg]); - if( safe_file_test (outputPath, Glib::FILE_TEST_IS_DIR)) { + if( Glib::file_test (outputPath, Glib::FILE_TEST_IS_DIR)) { outputDirectory = true; } } @@ -435,7 +456,7 @@ int processLineParams( int argc, char **argv ) // RT stop if any of them can't be loaded for any reason. if( iArg + 1 < argc ) { iArg++; - Glib::ustring fname = safe_filename_to_utf8 ( argv[iArg] ); + Glib::ustring fname = fname_to_utf8 (argv[iArg]); if (fname.at(0) == '-') { std::cerr << "Error: filename missing next to the -p switch" << std::endl; @@ -523,39 +544,54 @@ int processLineParams( int argc, char **argv ) break; case 'c': // MUST be last option - while( iArg + 1 < argc ) { + while (iArg + 1 < argc) { iArg++; - if( !safe_file_test( safe_filename_to_utf8(argv[iArg]), Glib::FILE_TEST_EXISTS )) { - std::cerr << argv[iArg] << " doesn't exist." << std::endl; + const auto argument = fname_to_utf8 (argv[iArg]); + + if (Glib::file_test (argument, Glib::FILE_TEST_IS_REGULAR)) { + inputFiles.emplace_back (argument); continue; } - if( safe_file_test( safe_filename_to_utf8(argv[iArg]), Glib::FILE_TEST_IS_DIR )) { - std::vector names; - Glib::RefPtr dir = Gio::File::create_for_path ( argv[iArg] ); - safe_build_file_list (dir, names, argv[iArg] ); + if (Glib::file_test (argument, Glib::FILE_TEST_IS_DIR)) { - for(size_t iFile = 0; iFile < names.size(); iFile++ ) { - if( !safe_file_test( names[iFile] , Glib::FILE_TEST_IS_DIR)) { - // skip files without extension and without sidecar files - Glib::ustring s(names[iFile]); - Glib::ustring::size_type ext = s.find_last_of('.'); - - if( Glib::ustring::npos == ext ) { - continue; - } - - if( ! s.substr(ext).compare( paramFileExtension )) { - continue; - } - - inputFiles.push_back( names[iFile] ); - } + auto dir = Gio::File::create_for_path (argument); + if (!dir || !dir->query_exists()) { + continue; } - } else { - inputFiles.push_back( safe_filename_to_utf8 (argv[iArg]) ); + + try { + + auto enumerator = dir->enumerate_children (); + + while (auto file = enumerator->next_file ()) { + + const auto fileName = Glib::build_filename (argument, file->get_name ()); + + if (Glib::file_test (fileName, Glib::FILE_TEST_IS_DIR)) { + continue; + } + + // skip files without extension and sidecar files + auto lastdot = fileName.find_last_of('.'); + if (lastdot == Glib::ustring::npos) { + continue; + } + + if (fileName.substr (lastdot).compare (paramFileExtension) == 0) { + continue; + } + + inputFiles.emplace_back (fileName); + } + + } catch (Glib::Exception&) {} + + continue; } + + std::cerr << "\"" << argument << "\" is neither a regular file nor a directory." << std::endl; } break; @@ -626,7 +662,7 @@ int processLineParams( int argc, char **argv ) } } } else { - argv1 = safe_filename_to_utf8 ( argv[iArg] ); + argv1 = fname_to_utf8 (argv[iArg]); if( outputDirectory ) { options.savePathFolder = outputPath; @@ -727,7 +763,7 @@ int processLineParams( int argc, char **argv ) continue; } - if( !overwriteFiles && safe_file_test( outputFile , Glib::FILE_TEST_EXISTS ) ) { + if( !overwriteFiles && Glib::file_test( outputFile , Glib::FILE_TEST_EXISTS ) ) { std::cerr << outputFile << " already exists: use -Y option to overwrite. This image has been skipped." << std::endl; continue; } @@ -768,7 +804,7 @@ int processLineParams( int argc, char **argv ) Glib::ustring sideProcessingParams = inputFile + paramFileExtension; // the "load" method don't reset the procparams values anymore, so values found in the procparam file override the one of currentParams - if( !safe_file_test( sideProcessingParams, Glib::FILE_TEST_EXISTS ) || currentParams.load ( sideProcessingParams )) { + if( !Glib::file_test( sideProcessingParams, Glib::FILE_TEST_EXISTS ) || currentParams.load ( sideProcessingParams )) { std::cerr << "Warning: sidecar file requested but not found for: " << sideProcessingParams << std::endl; } else { sideCarFound = true; diff --git a/rtgui/options.cc b/rtgui/options.cc index 3365970ed..53dfd8e38 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -21,10 +21,8 @@ #include #include #include "multilangmgr.h" -#include "../rtengine/safekeyfile.h" #include "addsetids.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "version.h" #ifdef _OPENMP @@ -70,13 +68,13 @@ inline bool Options::checkProfilePath(Glib::ustring &path) Glib::ustring p = getUserProfilePath(); - if (!p.empty() && safe_file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { return true; } p = getGlobalProfilePath(); - if (!p.empty() && safe_file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (path + paramFileExtension, Glib::FILE_TEST_EXISTS)) { return true; } else { return false; @@ -85,7 +83,7 @@ inline bool Options::checkProfilePath(Glib::ustring &path) bool Options::checkDirPath(Glib::ustring &path, Glib::ustring errString) { - if (safe_file_test (path, Glib::FILE_TEST_EXISTS) && safe_file_test (path, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (path, Glib::FILE_TEST_EXISTS) && Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) { return true; } else { if (!errString.empty()) { @@ -107,7 +105,7 @@ void Options::updatePaths() if (Glib::path_is_absolute(profilePath)) { // absolute path if (!checkDirPath (profilePath, "")) { - safe_g_mkdir_with_parents (profilePath, 511); + g_mkdir_with_parents (profilePath.c_str (), 511); if (!checkDirPath (profilePath, "")) { // had problems with mkdir_with_parents return value on OS X, just check dir again printf("Error: user's profiles' directory \"%s\" creation failed\n", profilePath.c_str()); @@ -140,7 +138,7 @@ void Options::updatePaths() tmpPath = Glib::build_filename(rtdir, profilePath); if (!checkDirPath (tmpPath, "")) { - safe_g_mkdir_with_parents (tmpPath, 511); + g_mkdir_with_parents (tmpPath.c_str (), 511); if (!checkDirPath (tmpPath, "")) { printf("Error: user's profiles' directory \"%s\" creation failed\n", tmpPath.c_str()); @@ -170,51 +168,51 @@ void Options::updatePaths() Glib::ustring preferredPath = getPreferredProfilePath(); // Paths are updated only if the user or global profile path is set - if (lastRgbCurvesDir.empty() || !safe_file_test (lastRgbCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastRgbCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastRgbCurvesDir.empty() || !Glib::file_test (lastRgbCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastRgbCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastRgbCurvesDir = preferredPath; } - if (lastLabCurvesDir.empty() || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastLabCurvesDir.empty() || !Glib::file_test (lastLabCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastLabCurvesDir = preferredPath; } - if (lastRetinexDir.empty() || !safe_file_test (lastRetinexDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastRetinexDir.empty() || !Glib::file_test (lastRetinexDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastLabCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastRetinexDir = preferredPath; } - if (lastDenoiseCurvesDir.empty() || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastDenoiseCurvesDir.empty() || !Glib::file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastDenoiseCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastDenoiseCurvesDir = preferredPath; } - if (lastWaveletCurvesDir.empty() || !safe_file_test (lastWaveletCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastWaveletCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastWaveletCurvesDir.empty() || !Glib::file_test (lastWaveletCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastWaveletCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastWaveletCurvesDir = preferredPath; } - if (lastPFCurvesDir.empty() || !safe_file_test (lastPFCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastPFCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastPFCurvesDir.empty() || !Glib::file_test (lastPFCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastPFCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastPFCurvesDir = preferredPath; } - if (lastHsvCurvesDir.empty() || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastHsvCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastHsvCurvesDir.empty() || !Glib::file_test (lastHsvCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastHsvCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastHsvCurvesDir = preferredPath; } - if (lastToneCurvesDir.empty() || !safe_file_test (lastToneCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastToneCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastToneCurvesDir.empty() || !Glib::file_test (lastToneCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastToneCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastToneCurvesDir = preferredPath; } - if (lastProfilingReferenceDir.empty() || !safe_file_test (lastProfilingReferenceDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastProfilingReferenceDir, Glib::FILE_TEST_IS_DIR)) { + if (lastProfilingReferenceDir.empty() || !Glib::file_test (lastProfilingReferenceDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastProfilingReferenceDir, Glib::FILE_TEST_IS_DIR)) { lastProfilingReferenceDir = preferredPath; } - if (lastVibranceCurvesDir.empty() || !safe_file_test (lastVibranceCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastVibranceCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastVibranceCurvesDir.empty() || !Glib::file_test (lastVibranceCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastVibranceCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastVibranceCurvesDir = preferredPath; } - if (loadSaveProfilePath.empty() || !safe_file_test (loadSaveProfilePath, Glib::FILE_TEST_EXISTS) || !safe_file_test (loadSaveProfilePath, Glib::FILE_TEST_IS_DIR)) { + if (loadSaveProfilePath.empty() || !Glib::file_test (loadSaveProfilePath, Glib::FILE_TEST_EXISTS) || !Glib::file_test (loadSaveProfilePath, Glib::FILE_TEST_IS_DIR)) { loadSaveProfilePath = preferredPath; } - if (lastBWCurvesDir.empty() || !safe_file_test (lastBWCurvesDir, Glib::FILE_TEST_EXISTS) || !safe_file_test (lastBWCurvesDir, Glib::FILE_TEST_IS_DIR)) { + if (lastBWCurvesDir.empty() || !Glib::file_test (lastBWCurvesDir, Glib::FILE_TEST_EXISTS) || !Glib::file_test (lastBWCurvesDir, Glib::FILE_TEST_IS_DIR)) { lastBWCurvesDir = preferredPath; } @@ -255,7 +253,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) p = getUserProfilePath(); Glib::ustring fullPath = Glib::build_filename(p, profName.substr(5) + paramFileExtension); - if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (fullPath, Glib::FILE_TEST_EXISTS)) { return Glib::path_get_dirname(fullPath); } } else if (p == "${G}") { @@ -263,7 +261,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) p = getGlobalProfilePath(); Glib::ustring fullPath = Glib::build_filename(p, profName.substr(5) + paramFileExtension); - if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (fullPath, Glib::FILE_TEST_EXISTS)) { return Glib::path_get_dirname(fullPath); } } else { @@ -271,7 +269,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) p = getUserProfilePath(); Glib::ustring fullPath = Glib::build_filename(p, profName + paramFileExtension); - if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (fullPath, Glib::FILE_TEST_EXISTS)) { // update the profile path profName = Glib::build_filename("${U}", profName); return Glib::path_get_dirname(fullPath); @@ -280,7 +278,7 @@ Glib::ustring Options::findProfilePath(Glib::ustring &profName) p = getGlobalProfilePath(); fullPath = Glib::build_filename(p, profName + paramFileExtension); - if (!p.empty() && safe_file_test (fullPath, Glib::FILE_TEST_EXISTS)) { + if (!p.empty() && Glib::file_test (fullPath, Glib::FILE_TEST_EXISTS)) { profName = Glib::build_filename("${G}", profName); return Glib::path_get_dirname(fullPath); } @@ -726,9 +724,10 @@ void Options::filterOutParsedExtensions () int Options::readFromFile (Glib::ustring fname) { setlocale(LC_NUMERIC, "C"); // to set decimal point to "." - rtengine::SafeKeyFile keyFile; - if( !safe_file_test(fname, Glib::FILE_TEST_EXISTS)) { + Glib::KeyFile keyFile; + + if( !Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) { return 1; } @@ -1774,23 +1773,29 @@ int Options::readFromFile (Glib::ustring fname) if (options.rtSettings.verbose) { printf("Options::readFromFile / Error code %d while reading values from \"%s\":\n%s\n", err.code(), fname.c_str(), err.what().c_str()); } + setDefaults (); } catch (...) { if (options.rtSettings.verbose) { printf("Options::readFromFile / Unknown exception while trying to load \"%s\"!\n", fname.c_str()); } + setDefaults (); } return 1; } -bool Options::safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustring& section, +bool Options::safeDirGet(const Glib::KeyFile& keyFile, const Glib::ustring& section, const Glib::ustring& entryName, Glib::ustring& destination) { - if (keyFile.has_key(section, entryName) && !keyFile.get_string(section, entryName).empty()) { - destination = keyFile.get_string(section, entryName); - return true; - } + try { + + if (keyFile.has_key (section, entryName) && !keyFile.get_string (section, entryName).empty ()) { + destination = keyFile.get_string (section, entryName); + return true; + } + + } catch(Glib::KeyFileError&) {} return false; } @@ -1798,9 +1803,13 @@ bool Options::safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustri int Options::saveToFile (Glib::ustring fname) { - rtengine::SafeKeyFile keyFile; - keyFile.set_boolean ("General", "TabbedEditor", tabbedUI); + Glib::ustring keyData; + try { + + Glib::KeyFile keyFile; + + keyFile.set_boolean ("General", "TabbedEditor", tabbedUI); keyFile.set_boolean ("General", "StoreLastProfile", savesParamsAtExit); if (startupDir == STARTUPDIR_HOME) { @@ -2099,7 +2108,15 @@ int Options::saveToFile (Glib::ustring fname) keyFile.set_string ("Dialogs", "LastVibranceCurvesDir", lastVibranceCurvesDir); keyFile.set_string ("Dialogs", "LastProfilingReferenceDir", lastProfilingReferenceDir); - FILE *f = safe_g_fopen (fname, "wt"); + keyData = keyFile.to_data (); + + } catch (Glib::KeyFileError&) {} + + if (keyData.empty ()) { + return 1; + } + + FILE *f = g_fopen (fname.c_str (), "wt"); if (f == NULL) { if (options.rtSettings.verbose) { @@ -2108,7 +2125,7 @@ int Options::saveToFile (Glib::ustring fname) return 1; } else { - fprintf (f, "%s", keyFile.to_data().c_str()); + fprintf (f, "%s", keyData.c_str ()); fclose (f); return 0; } @@ -2181,14 +2198,14 @@ bool Options::load () int r = options.readFromFile (Glib::build_filename(rtdir, "options")); // If the local option file does not exist or is broken, and the local cache folder does not exist, recreate it - if (r && !safe_g_mkdir_with_parents (rtdir, 511)) { + if (r && !g_mkdir_with_parents (rtdir.c_str (), 511)) { // Save the option file options.saveToFile (Glib::build_filename(rtdir, "options")); } #ifdef __APPLE__ // make sure .local/share exists on OS X so we don't get problems with recently-used.xbel - safe_g_mkdir_with_parents (g_get_user_data_dir(), 511); + g_mkdir_with_parents (g_get_user_data_dir(), 511); #endif } diff --git a/rtgui/options.h b/rtgui/options.h index 5bce466cb..c847e14fd 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -58,11 +58,6 @@ enum PPLoadLocation {PLL_Cache = 0, PLL_Input = 1}; enum CPBKeyType {CPBKT_TID = 0, CPBKT_NAME = 1, CPBKT_TID_NAME = 2}; enum prevdemo_t {PD_Sidecar = 1, PD_Fast = 0}; -namespace rtengine -{ -class SafeKeyFile; -} - class Options { @@ -87,7 +82,7 @@ private: * @param destination destination variable to store to * @return @c true if @p destination was changed */ - bool safeDirGet(const rtengine::SafeKeyFile& keyFile, const Glib::ustring& section, + bool safeDirGet(const Glib::KeyFile& keyFile, const Glib::ustring& section, const Glib::ustring& entryName, Glib::ustring& destination); public: diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 062c61ba2..f65094f53 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -375,6 +375,7 @@ void ParamsEdited::set (bool v) raw.xtranssensor.exBlackGreen = v; raw.xtranssensor.exBlackBlue = v; raw.caCorrection = v; + raw.caAutoStrength = v; raw.caBlue = v; raw.caRed = v; raw.hotPixelFilter = v; @@ -487,6 +488,8 @@ void ParamsEdited::set (bool v) dirpyrequalizer.enabled = v; dirpyrequalizer.gamutlab = v; + dirpyrequalizer.cbdlMethod = v; + for(int i = 0; i < 6; i++) { dirpyrequalizer.mult[i] = v; @@ -865,6 +868,7 @@ void ParamsEdited::initFrom (const std::vector raw.xtranssensor.exBlackGreen = raw.xtranssensor.exBlackGreen && p.raw.xtranssensor.blackgreen == other.raw.xtranssensor.blackgreen; raw.xtranssensor.exBlackBlue = raw.xtranssensor.exBlackBlue && p.raw.xtranssensor.blackblue == other.raw.xtranssensor.blackblue; raw.caCorrection = raw.caCorrection && p.raw.ca_autocorrect == other.raw.ca_autocorrect; + raw.caAutoStrength = raw.caAutoStrength && p.raw.caautostrength == other.raw.caautostrength; raw.caRed = raw.caRed && p.raw.cared == other.raw.cared; raw.caBlue = raw.caBlue && p.raw.cablue == other.raw.cablue; raw.hotPixelFilter = raw.hotPixelFilter && p.raw.hotPixelFilter == other.raw.hotPixelFilter; @@ -973,6 +977,7 @@ void ParamsEdited::initFrom (const std::vector dirpyrequalizer.enabled = dirpyrequalizer.enabled && p.dirpyrequalizer.enabled == other.dirpyrequalizer.enabled; dirpyrequalizer.gamutlab = dirpyrequalizer.gamutlab && p.dirpyrequalizer.gamutlab == other.dirpyrequalizer.gamutlab; + dirpyrequalizer.cbdlMethod = dirpyrequalizer.cbdlMethod && p.dirpyrequalizer.cbdlMethod == other.dirpyrequalizer.cbdlMethod; for(int i = 0; i < 6; i++) { dirpyrequalizer.mult[i] = dirpyrequalizer.mult[i] && p.dirpyrequalizer.mult[i] == other.dirpyrequalizer.mult[i]; @@ -2290,6 +2295,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; } + if (raw.caAutoStrength) { + toEdit.raw.caautostrength = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.caautostrength + mods.raw.caautostrength : mods.raw.caautostrength; + } + if (raw.caRed) { toEdit.raw.cared = dontforceSet && options.baBehav[ADDSET_RAWCACORR] ? toEdit.raw.cared + mods.raw.cared : mods.raw.cared; } @@ -2700,6 +2709,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.dirpyrequalizer.gamutlab = mods.dirpyrequalizer.gamutlab; } + if (dirpyrequalizer.cbdlMethod) { + toEdit.dirpyrequalizer.cbdlMethod = mods.dirpyrequalizer.cbdlMethod; + } + for(int i = 0; i < 6; i++) { if(dirpyrequalizer.mult[i]) { toEdit.dirpyrequalizer.mult[i] = dontforceSet && options.baBehav[ADDSET_DIRPYREQ] ? toEdit.dirpyrequalizer.mult[i] + mods.dirpyrequalizer.mult[i] : mods.dirpyrequalizer.mult[i]; @@ -2770,7 +2783,7 @@ bool RAWParamsEdited::XTransSensor::isUnchanged() const bool RAWParamsEdited::isUnchanged() const { - return bayersensor.isUnchanged() && xtranssensor.isUnchanged() && caCorrection && caRed && caBlue && hotPixelFilter && deadPixelFilter && hotDeadPixelThresh && darkFrame + return bayersensor.isUnchanged() && xtranssensor.isUnchanged() && caCorrection && caAutoStrength && caRed && caBlue && hotPixelFilter && deadPixelFilter && hotDeadPixelThresh && darkFrame && dfAuto && ff_file && ff_AutoSelect && ff_BlurRadius && ff_BlurType && exPos && exPreser && ff_AutoClipControl && ff_clipControl; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index acdeb89a7..c2654047a 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -646,7 +646,7 @@ public: bool enabled; bool gamutlab; bool mult[6]; - + bool cbdlMethod; bool threshold; bool skinprotect; bool hueskin; @@ -712,6 +712,7 @@ public: XTransSensor xtranssensor; bool caCorrection; + bool caAutoStrength; bool caRed; bool caBlue; bool hotPixelFilter; diff --git a/rtgui/placesbrowser.cc b/rtgui/placesbrowser.cc index 8275e90fa..ab3e3e7e2 100644 --- a/rtgui/placesbrowser.cc +++ b/rtgui/placesbrowser.cc @@ -17,11 +17,17 @@ * along with RawTherapee. If not, see . */ #include "placesbrowser.h" -#include "options.h" -#include "toolpanel.h" -#include "../rtengine/safegtk.h" + +#ifdef WIN32 +#include +#include +#include +#endif + #include "guiutils.h" #include "rtimage.h" +#include "options.h" +#include "toolpanel.h" PlacesBrowser::PlacesBrowser () { @@ -96,17 +102,14 @@ bool compareMountByRoot (Glib::RefPtr a, Glib::RefPtr b) void PlacesBrowser::refreshPlacesList () { - placesModel->clear (); // append home directory - Glib::RefPtr hfile = Gio::File::create_for_path (safe_get_user_home_dir()); // Will send back "My documents" on Windows now, which has no restricted access + Glib::RefPtr hfile = Gio::File::create_for_path (userHomeDir()); // Will send back "My documents" on Windows now, which has no restricted access if (hfile && hfile->query_exists()) { try { - Glib::RefPtr info = safe_query_file_info (hfile); - - if (info) { + if (auto info = hfile->query_info ()) { Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = info->get_display_name (); newrow[placesColumns.icon] = info->get_icon (); @@ -114,19 +117,15 @@ void PlacesBrowser::refreshPlacesList () newrow[placesColumns.type] = 4; newrow[placesColumns.rowSeparator] = false; } - } catch (Gio::Error&) { - /* This will be thrown if the path doesn't exist */ - } + } catch (Gio::Error&) {} } // append pictures directory - hfile = Gio::File::create_for_path (safe_get_user_picture_dir()); + hfile = Gio::File::create_for_path (userPicturesDir()); if (hfile && hfile->query_exists()) { try { - Glib::RefPtr info = safe_query_file_info (hfile); - - if (info) { + if (auto info = hfile->query_info ()) { Gtk::TreeModel::Row newrow = *(placesModel->append()); newrow[placesColumns.label] = info->get_display_name (); newrow[placesColumns.icon] = info->get_icon (); @@ -134,9 +133,7 @@ void PlacesBrowser::refreshPlacesList () newrow[placesColumns.type] = 4; newrow[placesColumns.rowSeparator] = false; } - } catch (Gio::Error&) { - /* This will be thrown if the path doesn't exist */ - } + } catch (Gio::Error&) {} } if (!placesModel->children().empty()) { @@ -235,16 +232,16 @@ void PlacesBrowser::refreshPlacesList () Glib::RefPtr hfile = Gio::File::create_for_path (options.favoriteDirs[i]); if (hfile && hfile->query_exists()) { - Glib::RefPtr info = safe_query_file_info (hfile); - - if (info) { - Gtk::TreeModel::Row newrow = *(placesModel->append()); - newrow[placesColumns.label] = info->get_display_name (); - newrow[placesColumns.icon] = info->get_icon (); - newrow[placesColumns.root] = hfile->get_parse_name (); - newrow[placesColumns.type] = 5; - newrow[placesColumns.rowSeparator] = false; - } + try { + if (auto info = hfile->query_info ()) { + Gtk::TreeModel::Row newrow = *(placesModel->append()); + newrow[placesColumns.label] = info->get_display_name (); + newrow[placesColumns.icon] = info->get_icon (); + newrow[placesColumns.root] = hfile->get_parse_name (); + newrow[placesColumns.type] = 5; + newrow[placesColumns.rowSeparator] = false; + } + } catch(Gio::Error&) {} } } } @@ -325,12 +322,12 @@ void PlacesBrowser::addPressed () Glib::RefPtr hfile = Gio::File::create_for_path (lastSelectedDir); if (hfile && hfile->query_exists()) { - Glib::RefPtr info = safe_query_file_info (hfile); - - if (info) { - options.favoriteDirs.push_back (hfile->get_parse_name ()); - refreshPlacesList (); - } + try { + if (auto info = hfile->query_info ()) { + options.favoriteDirs.push_back (hfile->get_parse_name ()); + refreshPlacesList (); + } + } catch(Gio::Error&) {} } } @@ -352,3 +349,52 @@ void PlacesBrowser::delPressed () refreshPlacesList (); } +Glib::ustring PlacesBrowser::userHomeDir () +{ +#ifdef WIN32 + + // get_home_dir crashes on some Windows configurations, + // so we rather use the safe native functions here. + WCHAR pathW[MAX_PATH]; + if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_PERSONAL, false)) { + + char pathA[MAX_PATH]; + if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) { + + return Glib::ustring (pathA); + } + } + + return Glib::ustring ("C:\\"); + +#else + + return Glib::get_home_dir (); + +#endif +} + +Glib::ustring PlacesBrowser::userPicturesDir () +{ +#ifdef WIN32 + + // get_user_special_dir crashes on some Windows configurations, + // so we rather use the safe native functions here. + WCHAR pathW[MAX_PATH]; + if (SHGetSpecialFolderPathW (NULL, pathW, CSIDL_MYPICTURES, false)) { + + char pathA[MAX_PATH]; + if (WideCharToMultiByte (CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0)) { + + return Glib::ustring (pathA); + } + } + + return Glib::ustring ("C:\\"); + +#else + + return Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES); + +#endif +} diff --git a/rtgui/placesbrowser.h b/rtgui/placesbrowser.h index b9d74648b..b3bed867c 100644 --- a/rtgui/placesbrowser.h +++ b/rtgui/placesbrowser.h @@ -72,6 +72,12 @@ public: void selectionChanged (); void addPressed (); void delPressed (); + +public: + + static Glib::ustring userHomeDir (); + static Glib::ustring userPicturesDir (); + }; inline void PlacesBrowser::setDirSelector (const PlacesBrowser::DirSelectionSlot& selectDir) diff --git a/rtgui/popupcommon.cc b/rtgui/popupcommon.cc index 74ed2ff4d..931755479 100644 --- a/rtgui/popupcommon.cc +++ b/rtgui/popupcommon.cc @@ -22,7 +22,6 @@ #include #include "multilangmgr.h" #include "popupcommon.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" #include "guiutils.h" diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index b3d675397..3e842b52c 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -25,7 +25,6 @@ #include "../rtengine/dfmanager.h" #include "../rtengine/ffmanager.h" #include -#include "../rtengine/safegtk.h" #include "rtimage.h" #ifdef _OPENMP #include @@ -1352,7 +1351,7 @@ void Preferences::parseDir (Glib::ustring dirname, std::vector& i Glib::ustring sname = *i; // ignore directories - if (!safe_file_test (fname, Glib::FILE_TEST_IS_DIR) && sname.size() >= ext.size() && sname.substr (sname.size() - ext.size(), ext.size()).casefold() == ext) { + if (!Glib::file_test (fname, Glib::FILE_TEST_IS_DIR) && sname.size() >= ext.size() && sname.substr (sname.size() - ext.size(), ext.size()).casefold() == ext) { items.push_back (sname.substr(0, sname.size() - ext.size())); } } @@ -1640,18 +1639,18 @@ void Preferences::fillPreferences () #ifdef WIN32 edPS->set_active (moptions.editorToSendTo == 2); - if (safe_file_test (moptions.gimpDir, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (moptions.gimpDir, Glib::FILE_TEST_IS_DIR)) { gimpDir->set_current_folder (moptions.gimpDir); } - if (safe_file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { psDir->set_current_folder (moptions.psDir); } #elif defined __APPLE__ edPS->set_active (moptions.editorToSendTo == 2); - if (safe_file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (moptions.psDir, Glib::FILE_TEST_IS_DIR)) { psDir->set_current_folder (moptions.psDir); } @@ -1940,18 +1939,17 @@ void Preferences::bundledProfilesChanged () void Preferences::iccDirChanged () { - const Glib::ustring currentSelection = monProfile->get_active_text (); + const auto currentSelection = monProfile->get_active_text (); + const auto profiles = rtengine::ICCStore::getInstance ()->getProfilesFromDir (iccDir->get_filename ()); - monProfile->clear(); + monProfile->remove_all(); monProfile->append (M("PREFERENCES_PROFILE_NONE")); - monProfile->set_active (0); - const std::vector profiles = rtengine::ICCStore::getInstance ()->getProfilesFromDir (iccDir->get_filename ()); - for (std::vector::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile) - monProfile->append (*profile); + for (const auto& profile : profiles) + monProfile->append (profile); - monProfile->set_active_text (currentSelection); + setActiveTextOrIndex(*monProfile, currentSelection, 0); } void Preferences::storeCurrentValue() diff --git a/rtgui/preprocess.cc b/rtgui/preprocess.cc index 1bfad7cc3..44d054214 100644 --- a/rtgui/preprocess.cc +++ b/rtgui/preprocess.cc @@ -18,7 +18,6 @@ */ #include "preprocess.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/rtgui/previewloader.cc b/rtgui/previewloader.cc index 83d7cd2d2..b5fc95f40 100644 --- a/rtgui/previewloader.cc +++ b/rtgui/previewloader.cc @@ -21,7 +21,6 @@ #include "previewloader.h" #include "guiutils.h" #include "threadutils.h" -#include "../rtengine/safegtk.h" #ifdef _OPENMP #include @@ -123,7 +122,7 @@ public: try { Thumbnail* tmb = 0; { - if (safe_file_test(j.dir_entry_, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test(j.dir_entry_, Glib::FILE_TEST_EXISTS)) { tmb = cacheMgr->getEntry(j.dir_entry_); } } diff --git a/rtgui/profilepanel.cc b/rtgui/profilepanel.cc index df644f70f..a40434128 100644 --- a/rtgui/profilepanel.cc +++ b/rtgui/profilepanel.cc @@ -21,7 +21,6 @@ #include "profilestore.h" #include "clipboard.h" #include "multilangmgr.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" using namespace rtengine; @@ -272,24 +271,14 @@ void ProfilePanel::save_clicked (GdkEventButton* event) dialog.set_current_name (lastFilename); //Add the user's default (or global if multiuser=false) profile path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(options.getPreferredProfilePath())) -#endif - try { - dialog.add_shortcut_folder(options.getPreferredProfilePath()); - } catch (Glib::Error &err) {} + try { + dialog.add_shortcut_folder(options.getPreferredProfilePath()); + } catch (Glib::Error&) {} //Add the image's path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(imagePath)) -#endif - try { - dialog.add_shortcut_folder(imagePath); - } catch (Glib::Error &err) {} + try { + dialog.add_shortcut_folder(imagePath); + } catch (Glib::Error&) {} //Add response buttons the the dialog: dialog.add_button(M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); @@ -447,24 +436,14 @@ void ProfilePanel::load_clicked (GdkEventButton* event) bindCurrentFolder (dialog, options.loadSaveProfilePath); //Add the user's default (or global if multiuser=false) profile path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(options.getPreferredProfilePath())) -#endif - try { - dialog.add_shortcut_folder(options.getPreferredProfilePath()); - } catch (Glib::Error &err) {} + try { + dialog.add_shortcut_folder(options.getPreferredProfilePath()); + } catch (Glib::Error&) {} //Add the image's path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(imagePath)) -#endif - try { - dialog.add_shortcut_folder(imagePath); - } catch (Glib::Error &err) {} + try { + dialog.add_shortcut_folder(imagePath); + } catch (Glib::Error&) {} //Add response buttons the the dialog: dialog.add_button(M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL); diff --git a/rtgui/profilestore.cc b/rtgui/profilestore.cc index 24619ba02..d95e7d53f 100644 --- a/rtgui/profilestore.cc +++ b/rtgui/profilestore.cc @@ -20,7 +20,6 @@ #include "options.h" #include "toolpanel.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" ProfileStore profileStore; @@ -168,7 +167,7 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath unsigned int folder = 0; // folder's own Id // reload the available profiles from the profile dir - if (!realPath.empty() && safe_file_test(realPath, Glib::FILE_TEST_EXISTS) && safe_file_test (realPath, Glib::FILE_TEST_IS_DIR)) { + if (!realPath.empty() && Glib::file_test(realPath, Glib::FILE_TEST_EXISTS) && Glib::file_test (realPath, Glib::FILE_TEST_IS_DIR)) { // add this entry to the folder list folders.push_back(virtualPath); @@ -199,7 +198,7 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath Glib::ustring fname = Glib::build_filename(realPath, currDir); - if (safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) { + if (Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { Glib::ustring vp(Glib::build_filename(virtualPath, currDir)); Glib::ustring rp(Glib::build_filename(realPath, currDir)); fileFound = parseDir (rp, vp, currDir, folder, level + 1, 0); diff --git a/rtgui/rawcacorrection.cc b/rtgui/rawcacorrection.cc index 0e14182cf..d619ab112 100644 --- a/rtgui/rawcacorrection.cc +++ b/rtgui/rawcacorrection.cc @@ -18,7 +18,6 @@ */ #include "rawcacorrection.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include "rtimage.h" @@ -33,6 +32,14 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_CHROM Gtk::Image* icablueR = Gtk::manage (new RTImage ("ajd-ca-blue2.png")); caAutocorrect = Gtk::manage(new Gtk::CheckButton((M("TP_RAWCACORR_AUTO")))); + + caStrength = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CASTR"), 2.0, 8.0, 0.5, 6.0)); + caStrength->setAdjusterListener (this); + if (caStrength->delay < options.adjusterMaxDelay) { + caStrength->delay = options.adjusterMaxDelay; + } + +// caStrength->show(); caRed = Gtk::manage(new Adjuster (M("TP_RAWCACORR_CARED"), -4.0, 4.0, 0.1, 0, icaredL, icaredR)); caRed->setAdjusterListener (this); @@ -51,6 +58,7 @@ RAWCACorr::RAWCACorr () : FoldableToolPanel(this, "rawcacorrection", M("TP_CHROM caBlue->show(); pack_start( *caAutocorrect, Gtk::PACK_SHRINK, 4); +// pack_start( *caStrength, Gtk::PACK_SHRINK, 4); pack_start( *caRed, Gtk::PACK_SHRINK, 4); pack_start( *caBlue, Gtk::PACK_SHRINK, 4); @@ -64,17 +72,20 @@ void RAWCACorr::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi if(pedited ) { caAutocorrect->set_inconsistent(!pedited->raw.caCorrection); + caStrength->setEditedState( pedited->raw.caAutoStrength ? Edited : UnEdited ); caRed->setEditedState( pedited->raw.caRed ? Edited : UnEdited ); caBlue->setEditedState( pedited->raw.caBlue ? Edited : UnEdited ); } lastCA = pp->raw.ca_autocorrect; + caStrength->set_sensitive(pp->raw.ca_autocorrect); // disable Red and Blue sliders when caAutocorrect is enabled caRed->set_sensitive(!pp->raw.ca_autocorrect); caBlue->set_sensitive(!pp->raw.ca_autocorrect); caAutocorrect->set_active(pp->raw.ca_autocorrect); + caStrength->setValue (pp->raw.caautostrength); caRed->setValue (pp->raw.cared); caBlue->setValue (pp->raw.cablue); @@ -85,11 +96,13 @@ void RAWCACorr::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi void RAWCACorr::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited) { pp->raw.ca_autocorrect = caAutocorrect->get_active(); + pp->raw.caautostrength = caStrength->getValue(); pp->raw.cared = caRed->getValue(); pp->raw.cablue = caBlue->getValue(); if (pedited) { pedited->raw.caCorrection = !caAutocorrect->get_inconsistent(); + pedited->raw.caAutoStrength = caStrength->getEditedState (); pedited->raw.caRed = caRed->getEditedState (); pedited->raw.caBlue = caBlue->getEditedState (); } @@ -106,6 +119,8 @@ void RAWCACorr::adjusterChanged (Adjuster* a, double newval) listener->panelChanged (EvPreProcessCARed, value ); } else if (a == caBlue) { listener->panelChanged (EvPreProcessCABlue, value ); +// } else if (a == caStrength) { +// listener->panelChanged (EvPreProcessCAStrength, value ); } } } @@ -113,19 +128,23 @@ void RAWCACorr::adjusterChanged (Adjuster* a, double newval) void RAWCACorr::setBatchMode(bool batchMode) { ToolPanel::setBatchMode (batchMode); + caStrength->showEditedCB (); caRed->showEditedCB (); caBlue->showEditedCB (); } void RAWCACorr::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited) { + caStrength->setDefault( defParams->raw.caautostrength); caRed->setDefault( defParams->raw.cared); caBlue->setDefault( defParams->raw.cablue); if (pedited) { + caStrength->setDefaultEditedState( pedited->raw.caAutoStrength ? Edited : UnEdited); caRed->setDefaultEditedState( pedited->raw.caRed ? Edited : UnEdited); caBlue->setDefaultEditedState( pedited->raw.caBlue ? Edited : UnEdited); } else { + caStrength->setDefaultEditedState( Irrelevant ); caRed->setDefaultEditedState( Irrelevant ); caBlue->setDefaultEditedState( Irrelevant ); } @@ -159,6 +178,7 @@ void RAWCACorr::caCorrectionChanged() } }*/ + caStrength->set_sensitive(caAutocorrect->get_active ()); // disable Red and Blue sliders when caAutocorrect is enabled caRed->set_sensitive(!caAutocorrect->get_active ()); caBlue->set_sensitive(!caAutocorrect->get_active ()); @@ -179,6 +199,7 @@ void RAWCACorr::caCorrectionChanged() void RAWCACorr::setAdjusterBehavior (bool caadd) { + caStrength->setAddMode(caadd); caRed->setAddMode(caadd); caBlue->setAddMode(caadd); } @@ -186,6 +207,7 @@ void RAWCACorr::setAdjusterBehavior (bool caadd) void RAWCACorr::trimValues (rtengine::procparams::ProcParams* pp) { + caStrength->trimValue(pp->raw.caautostrength); caRed->trimValue(pp->raw.cared); caBlue->trimValue(pp->raw.cablue); } diff --git a/rtgui/rawcacorrection.h b/rtgui/rawcacorrection.h index 7d41d9547..82df2c3af 100644 --- a/rtgui/rawcacorrection.h +++ b/rtgui/rawcacorrection.h @@ -29,6 +29,7 @@ class RAWCACorr : public ToolParamBlock, public AdjusterListener, public Foldabl protected: Gtk::CheckButton* caAutocorrect; + Adjuster* caStrength; Adjuster* caRed; Adjuster* caBlue; bool lastCA; diff --git a/rtgui/rawexposure.cc b/rtgui/rawexposure.cc index 746b453cf..56fcf7ec9 100644 --- a/rtgui/rawexposure.cc +++ b/rtgui/rawexposure.cc @@ -18,7 +18,6 @@ */ #include "rawexposure.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/rtgui/rtimage.cc b/rtgui/rtimage.cc index 56f2ae46a..464123b0f 100644 --- a/rtgui/rtimage.cc +++ b/rtgui/rtimage.cc @@ -19,160 +19,189 @@ */ #include "rtimage.h" -#include "../rtengine/safegtk.h" -extern Glib::ustring argv0; -extern Options options; +#include -std::vector imagesPaths; -std::map > pixBufMap; // List of image buffers in order to live update them on theme switch and to avoid a lot of file accesses +#include "options.h" -/* - * RTImage is a derived class of Gtk::Image, in order to handle theme related iconsets - */ -RTImage::RTImage(Glib::ustring fileName, Glib::ustring rtlFileName) : Gtk::Image() +namespace { - Glib::ustring mapKey; - if (rtlFileName.length()) { - if (get_direction() == Gtk::TEXT_DIR_RTL) { - mapKey = rtlFileName; - } else { - mapKey = fileName; +std::vector imagePaths; +std::map> pixbufCache; + +bool loadIconSet(const Glib::ustring& iconSet) +{ + try { + + Glib::KeyFile keyFile; + keyFile.load_from_file (iconSet); + + auto iconSetDir = keyFile.get_string ("General", "Iconset"); + + if (!iconSetDir.empty ()) { + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "actions")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir)); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "devices")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "places")); } + + iconSetDir = keyFile.get_string ("General", "FallbackIconset"); + + if (!iconSetDir.empty ()) { + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "actions")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir)); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "devices")); + imagePaths.push_back (Glib::build_filename (argv0, "images", iconSetDir, "places")); + } + + return true; + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to load icon set \"" << iconSet << "\": " << exception.what() << std::endl; + } + + return false; + + } +} + +} + +RTImage::RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName) : Gtk::Image() +{ + Glib::ustring imageName; + + if (!rtlFileName.empty () && get_direction () == Gtk::TEXT_DIR_RTL) { + imageName = rtlFileName; } else { - mapKey = fileName; + imageName = fileName; } - std::map >::iterator it; - it = pixBufMap.find(mapKey); + changeImage (imageName); +} - if (it != pixBufMap.end()) { - set(it->second); - } else { - Glib::RefPtr tempPixPuf = Gdk::Pixbuf::create_from_file(findIconAbsolutePath(mapKey)); - pixBufMap.insert(std::pair >(mapKey, tempPixPuf)); - set(tempPixPuf); +void RTImage::changeImage (const Glib::ustring& imageName) +{ + clear (); + + auto iterator = pixbufCache.find (imageName); + + if (iterator == pixbufCache.end ()) { + const auto imagePath = findIconAbsolutePath (imageName); + const auto pixbuf = Gdk::Pixbuf::create_from_file (imagePath); + + iterator = pixbufCache.emplace (imageName, pixbuf).first; } + + set(iterator->second); } void RTImage::updateImages() { - std::map >::iterator it; - - for (it = pixBufMap.begin(); it != pixBufMap.end(); ++it) { - Glib::ustring fullPath = findIconAbsolutePath(it->first); - it->second = Gdk::Pixbuf::create_from_file(fullPath); + for (auto& entry : pixbufCache) { + const auto imagePath = findIconAbsolutePath (entry.first); + entry.second = Gdk::Pixbuf::create_from_file (imagePath); } } -// DONE (was TODO: Maybe this could be optimized: in order to avoid looking up for an icon file in the filesystem on each popupmenu selection, maybe we could find a way to copy the image data from another RTImage) -void RTImage::changeImage(Glib::ustring &newImage) +Glib::ustring RTImage::findIconAbsolutePath (const Glib::ustring& iconName) { - clear(); - std::map >::iterator it; - it = pixBufMap.find(newImage); - - if (it != pixBufMap.end()) { - set(it->second); - } else { - Glib::ustring fullPath = findIconAbsolutePath(newImage); - Glib::RefPtr tempPixPuf = Gdk::Pixbuf::create_from_file(fullPath); - pixBufMap.insert(std::pair >(newImage, tempPixPuf)); - set(tempPixPuf); - } -} - -Glib::ustring RTImage::findIconAbsolutePath(const Glib::ustring &iconFName) -{ - Glib::ustring path; - - for (unsigned int i = 0; i < imagesPaths.size(); i++) { - path = Glib::build_filename(imagesPaths[i], iconFName); - - if (safe_file_test(path, Glib::FILE_TEST_EXISTS)) { - return path; - } - } - - printf("\"%s\" not found!\n", iconFName.c_str()); - return ""; -} - -void RTImage::setPaths(Options &opt) -{ - imagesPaths.clear(); - - /* - * Forcing the Dark theme, so reading the .iconset file is useless for now - * - * - Glib::ustring configFilename; - rtengine::SafeKeyFile keyFile; - bool hasKeyFile = true; - - // system theme will use the theme set in system.iconset - if (opt.useSystemTheme) { - configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", "system.iconset")); - } - // Gtk theme will use the theme set in it's *.iconset fiel, if it exists - else { - configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", Glib::ustring::format(opt.theme, ".iconset"))); - } - try { - if (!safe_file_test(configFilename, Glib::FILE_TEST_EXISTS) || !keyFile.load_from_file (configFilename)) { - // ...otherwise fallback to the iconset set in default.iconset - configFilename = Glib::build_filename(argv0, Glib::build_filename("themes", "default.iconset")); - if (!keyFile.load_from_file (configFilename)) { - hasKeyFile = false; + for (const auto& imagePath : imagePaths) { + const auto iconPath = Glib::build_filename(imagePath, iconName); + + if (Glib::file_test(iconPath, Glib::FILE_TEST_IS_REGULAR)) { + return iconPath; } } - } catch (Glib::Error &err) { - if (options.rtSettings.verbose) { - printf("RTImage::setPaths / Error code %d while reading values from \"%s\":\n%s\n", err.code(), configFilename.c_str(), err.what().c_str()); + + } catch(const Glib::Exception&) {} + + if (options.rtSettings.verbose) { + std::cerr << "Icon \"" << iconName << "\" could not be found!" << std::endl; + } + + return Glib::ustring(); +} + +void RTImage::setPaths (const Options& options) +{ + // TODO: Forcing the Dark theme, so reading the icon set files is useless for now... + + /*Glib::ustring iconSet; + + // Either use the system icon set or the one specified in the options. + if (options.useSystemTheme) { + iconSet = Glib::build_filename (argv0, "themes", "system.iconset"); + } else { + iconSet = Glib::build_filename (argv0, "themes", options.theme + ".iconset"); + } + + imagePaths.clear (); + + if (!loadIconSet (iconSet)) { + // If the preferred icon set is unavailable, fall back to the default icon set. + loadIconSet (Glib::build_filename (argv0, "themes", "Default.iconset")); + }*/ + + imagePaths.clear (); + + imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark")); + imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "actions")); + imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "devices")); + imagePaths.push_back (Glib::build_filename(argv0, "images", "Dark", "places")); + + // The images folder is the second fallback solution. + imagePaths.push_back (Glib::build_filename(argv0, "images")); +} + +Glib::RefPtr RTImage::createFromFile (const Glib::ustring& fileName) +{ + Glib::RefPtr pixbuf; + + try { + + const auto filePath = findIconAbsolutePath (fileName); + + if (!filePath.empty ()) { + pixbuf = Gdk::Pixbuf::create_from_file (filePath); } - } catch (...) { + + } catch (const Glib::Exception& exception) { + if (options.rtSettings.verbose) { - printf("RTImage::setPaths / Unknown exception while trying to load \"%s\"!\n", configFilename.c_str()); + std::cerr << "Failed to load image \"" << fileName << "\": " << exception.what() << std::endl; + } + + } + + return pixbuf; +} + +Cairo::RefPtr RTImage::createFromPng (const Glib::ustring& fileName) +{ + Cairo::RefPtr surface; + + try { + + const auto filePath = findIconAbsolutePath (fileName); + + if (!filePath.empty()) { + surface = Cairo::ImageSurface::create_from_png (Glib::locale_from_utf8 (filePath)); + } + + } catch (const Glib::Exception& exception) { + + if (options.rtSettings.verbose) { + std::cerr << "Failed to load PNG \"" << fileName << "\": " << exception.what() << std::endl; } } - if (hasKeyFile && keyFile.has_group ("General")) { - Glib::ustring iSet; - - if (keyFile.has_key ("General", "Iconset")) { - iSet = keyFile.get_string ("General", "Iconset"); - } - - if (iSet.length()) { - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "actions")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", iSet))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "devices")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "places")))); - } - - iSet.clear(); - - if (keyFile.has_key ("General", "FallbackIconset")) { - iSet = keyFile.get_string ("General", "FallbackIconset"); - } - - if (iSet.length()) { - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "actions")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", iSet))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "devices")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename(iSet, "places")))); - } - }*/ - - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename("Dark", "actions")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", "Dark"))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename("Dark", "devices")))); - imagesPaths.push_back (Glib::build_filename(argv0, Glib::build_filename("images", Glib::build_filename("Dark", "places")))); - - // The images/ folder is the second fallback solution - imagesPaths.push_back (Glib::build_filename(argv0, "images")); + return surface; } + diff --git a/rtgui/rtimage.h b/rtgui/rtimage.h index de5ef9334..cfc7a5fa1 100644 --- a/rtgui/rtimage.h +++ b/rtgui/rtimage.h @@ -19,17 +19,26 @@ #ifndef _RTIMAGE_ #define _RTIMAGE_ -#include -#include "options.h" +#include +class Options; + +/** + * @brief A derived class of Gtk::Image in order to handle theme-related icon sets. + */ class RTImage : public Gtk::Image { public: - RTImage(Glib::ustring fileName, Glib::ustring rtlFileName = ""); - static void setPaths(Options &opt); - static void updateImages(); - void changeImage(Glib::ustring &newImage); - static Glib::ustring findIconAbsolutePath(const Glib::ustring &iconFName); + RTImage (const Glib::ustring& fileName, const Glib::ustring& rtlFileName = Glib::ustring()); + + void changeImage (const Glib::ustring& imageName); + static void updateImages (); + + static Glib::ustring findIconAbsolutePath (const Glib::ustring& iconName); + static void setPaths (const Options& options); + + static Glib::RefPtr createFromFile (const Glib::ustring& fileName); + static Cairo::RefPtr createFromPng (const Glib::ustring& fileName); }; #endif diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index 726b86eaa..82ac5d38a 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -19,7 +19,6 @@ #include "saveasdlg.h" #include "multilangmgr.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include "rtimage.h" extern Options options; @@ -224,7 +223,7 @@ void SaveAsDialog::okPressed () // checking if the filename field is empty. The user have to click Cancel if he don't want to specify a filename // NB: There seem to be a bug in Gtkmm2.22 / FileChooserWidget : if you suppress the filename entry and // click on a folder in the list, the filename field is empty but get_filename will return the folder's path :/ - if (!fname.length() || safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) { + if (!fname.length() || Glib::file_test (fname, Glib::FILE_TEST_IS_DIR)) { Glib::ustring msg_ = Glib::ustring("") + M("MAIN_MSG_EMPTYFILENAME") + ""; Gtk::MessageDialog msgd (*this, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true); msgd.run (); @@ -286,20 +285,13 @@ void SaveAsDialog::setInitialFileName (Glib::ustring fname) fchooser->set_current_name(fname); } -void SaveAsDialog::setImagePath (Glib::ustring ipath) +void SaveAsDialog::setImagePath (const Glib::ustring& imagePath) { + const auto dirName = Glib::path_get_dirname (imagePath); - Glib::ustring path = Glib::path_get_dirname(ipath); - - //Add the image's path to the Shortcut list -#ifdef WIN32 - - // Dirty workaround, waiting for a clean solution by using exceptions! - if (!safe_is_shortcut_dir(path)) -#endif - try { - fchooser->add_shortcut_folder(path); - } catch (Glib::Error &err) {} + try { + fchooser->add_shortcut_folder (dirName); + } catch (Glib::Error&) {} } diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index 2538fe61e..9d3b7de1a 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -58,7 +58,7 @@ public: int getSaveMethodNum (); void setInitialFileName (Glib::ustring iname); - void setImagePath (Glib::ustring ipath); + void setImagePath (const Glib::ustring& imagePath); void okPressed (); void cancelPressed (); diff --git a/rtgui/sharpenedge.cc b/rtgui/sharpenedge.cc index 880240f04..d21fe54aa 100644 --- a/rtgui/sharpenedge.cc +++ b/rtgui/sharpenedge.cc @@ -18,7 +18,6 @@ */ #include "sharpenedge.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include diff --git a/rtgui/sharpenmicro.cc b/rtgui/sharpenmicro.cc index 49c36e99f..2ca0ddf44 100644 --- a/rtgui/sharpenmicro.cc +++ b/rtgui/sharpenmicro.cc @@ -18,7 +18,6 @@ */ #include "sharpenmicro.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include #include diff --git a/rtgui/soundman.h b/rtgui/soundman.h index a778a006a..dd8e515fc 100644 --- a/rtgui/soundman.h +++ b/rtgui/soundman.h @@ -21,7 +21,10 @@ #ifndef _SOUNDMAN_ #define _SOUNDMAN_ -#include "../rtengine/safegtk.h" +namespace Glib +{ +class ustring; +} class SoundManager { diff --git a/rtgui/splash.cc b/rtgui/splash.cc index 02fcc7cfc..f34526c9c 100644 --- a/rtgui/splash.cc +++ b/rtgui/splash.cc @@ -17,9 +17,11 @@ * along with RawTherapee. If not, see . */ #include "splash.h" -#include "multilangmgr.h" + #include -#include "../rtengine/safegtk.h" + +#include "multilangmgr.h" +#include "rtimage.h" extern Glib::ustring creditsPath; extern Glib::ustring licensePath; @@ -28,8 +30,7 @@ extern Glib::ustring versionSuffixString; SplashImage::SplashImage () { - - pixbuf = safe_create_from_file ("splash.png"); + pixbuf = RTImage::createFromFile ("splash.png"); set_size_request (pixbuf->get_width(), pixbuf->get_height()); } @@ -100,8 +101,8 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t // Tab 2: the informations about the current version std::string buildFileName = Glib::build_filename (creditsPath, "AboutThisBuild.txt"); - if ( safe_file_test(buildFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = safe_g_fopen (buildFileName, "rt"); + if ( Glib::file_test(buildFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = g_fopen (buildFileName.c_str (), "rt"); if (f != NULL) { char* buffer = new char[1024]; @@ -131,8 +132,8 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t // Tab 3: the credits std::string creditsFileName = Glib::build_filename (creditsPath, "AUTHORS.txt"); - if ( safe_file_test(creditsFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = safe_g_fopen (creditsFileName, "rt"); + if ( Glib::file_test(creditsFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = g_fopen (creditsFileName.c_str (), "rt"); if (f != NULL) { char* buffer = new char[1024]; @@ -163,8 +164,8 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t // Tab 4: the license std::string licenseFileName = Glib::build_filename (licensePath, "LICENSE.txt"); - if ( safe_file_test(licenseFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = safe_g_fopen (licenseFileName, "rt"); + if ( Glib::file_test(licenseFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = g_fopen (licenseFileName.c_str (), "rt"); if (f != NULL) { char* buffer = new char[1024]; @@ -196,8 +197,8 @@ Splash::Splash (Gtk::Window& parent) : Gtk::Dialog(M("GENERAL_ABOUT"), parent, t // Tab 5: the Release Notes std::string releaseNotesFileName = Glib::build_filename (creditsPath, "RELEASE_NOTES.txt"); - if ( safe_file_test(releaseNotesFileName, (Glib::FILE_TEST_EXISTS)) ) { - FILE *f = safe_g_fopen (releaseNotesFileName, "rt"); + if ( Glib::file_test(releaseNotesFileName, (Glib::FILE_TEST_EXISTS)) ) { + FILE *f = g_fopen (releaseNotesFileName.c_str (), "rt"); if (f != NULL) { char* buffer = new char[1024]; diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 5e132cc14..673c49efe 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -29,7 +29,7 @@ #include "guiutils.h" #include "profilestore.h" #include "batchqueue.h" -#include "../rtengine/safegtk.h" +#include "extprog.h" using namespace rtengine::procparams; @@ -153,7 +153,7 @@ void Thumbnail::_generateThumbnailImage () cfs.supported = true; needsReProcessing = true; - cfs.save (getCacheFileName ("data") + ".txt"); + cfs.save (getCacheFileName ("data", ".txt")); generateExifDateTimeStrings (); } @@ -238,7 +238,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu if (options.paramsLoadLocation == PLL_Input) { outFName = fname + paramFileExtension; } else { - outFName = getCacheFileName("profiles") + paramFileExtension; + outFName = getCacheFileName("profiles", paramFileExtension); } exifDir->CPBDump(tmpFileName, fname, outFName, @@ -254,20 +254,16 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu printf("Custom profile builder's command line: %s\n", Glib::ustring(cmdLine).c_str()); } - bool success = safe_spawn_command_line_sync (cmdLine); + bool success = ExtProgStore::spawnCommandSync (cmdLine); // Now they SHOULD be there (and potentially "partial"), so try to load them and store it as a full procparam if (success) { loadProcParams(); } - if (safe_file_test(tmpFileName, Glib::FILE_TEST_EXISTS )) { - safe_g_remove (tmpFileName); - } + g_remove (tmpFileName.c_str ()); - if (imageMetaData) { - delete imageMetaData; - } + delete imageMetaData; } if (returnParams && hasProcParams()) { @@ -309,11 +305,11 @@ void Thumbnail::loadProcParams () // if no success, try to load the cached version of the procparams if (!pparamsValid) { - pparamsValid = !pparams.load (getCacheFileName ("profiles") + paramFileExtension); + pparamsValid = !pparams.load (getCacheFileName ("profiles", paramFileExtension)); } } else { // try to load it from cache - pparamsValid = !pparams.load (getCacheFileName ("profiles") + paramFileExtension); + pparamsValid = !pparams.load (getCacheFileName ("profiles", paramFileExtension)); // if no success, try to load it from params file next to the image file if (!pparamsValid) { @@ -364,25 +360,15 @@ void Thumbnail::clearProcParams (int whoClearedIt) updateCache(); } else { // remove param file from cache - Glib::ustring fname_ = getCacheFileName ("profiles") + paramFileExtension; - - if (safe_file_test (fname_, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (fname_); - } + Glib::ustring fname_ = getCacheFileName ("profiles", paramFileExtension); + g_remove (fname_.c_str ()); // remove param file located next to the file -// fname_ = removeExtension(fname) + paramFileExtension; fname_ = fname + paramFileExtension; - - if (safe_file_test(fname_, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (fname_); - } + g_remove (fname_.c_str ()); fname_ = removeExtension(fname) + paramFileExtension; - - if (safe_file_test (fname_, Glib::FILE_TEST_EXISTS)) { - safe_g_remove (fname_); - } + g_remove (fname_.c_str ()); if (cfs.format == FT_Raw && options.internalThumbIfUntouched && cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL) { // regenerate thumbnail, ie load the quick thumb again. For the rare formats not supporting quick thumbs this will @@ -464,10 +450,10 @@ void Thumbnail::imageDeveloped () { cfs.recentlySaved = true; - cfs.save (getCacheFileName ("data") + ".txt"); + cfs.save (getCacheFileName ("data", ".txt")); if (options.saveParamsCache) { - pparams.save (getCacheFileName ("profiles") + paramFileExtension); + pparams.save (getCacheFileName ("profiles", paramFileExtension)); } } @@ -778,14 +764,14 @@ void Thumbnail::_loadThumbnail(bool firstTrial) tpp->isRaw = (cfs.format == (int) FT_Raw); // load supplementary data - bool succ = tpp->readData (getCacheFileName ("data") + ".txt"); + bool succ = tpp->readData (getCacheFileName ("data", ".txt")); if (succ) { tpp->getAutoWBMultipliers(cfs.redAWBMul, cfs.greenAWBMul, cfs.blueAWBMul); } // thumbnail image - succ = succ && tpp->readImage (getCacheFileName ("images")); + succ = succ && tpp->readImage (getCacheFileName ("images", "")); if (!succ && firstTrial) { _generateThumbnailImage (); @@ -805,10 +791,10 @@ void Thumbnail::_loadThumbnail(bool firstTrial) if ( cfs.thumbImgType == CacheImageData::FULL_THUMBNAIL ) { // load aehistogram - tpp->readAEHistogram (getCacheFileName ("aehistograms")); + tpp->readAEHistogram (getCacheFileName ("aehistograms", "")); // load embedded profile - tpp->readEmbProfile (getCacheFileName ("embprofiles") + ".icc"); + tpp->readEmbProfile (getCacheFileName ("embprofiles", ".icc")); tpp->init (); } @@ -847,24 +833,24 @@ void Thumbnail::_saveThumbnail () return; } - if (safe_g_remove (getCacheFileName ("images") + ".rtti") == -1) { + if (g_remove (getCacheFileName ("images", ".rtti").c_str ()) != 0) { // No file deleted, so we try to deleted obsolete files, if any - safe_g_remove (getCacheFileName ("images") + ".cust"); - safe_g_remove (getCacheFileName ("images") + ".cust16"); - safe_g_remove (getCacheFileName ("images") + ".jpg"); + g_remove (getCacheFileName ("images", ".cust").c_str ()); + g_remove (getCacheFileName ("images", ".cust16").c_str ()); + g_remove (getCacheFileName ("images", ".jpg").c_str ()); } // save thumbnail image - tpp->writeImage (getCacheFileName ("images"), 1); + tpp->writeImage (getCacheFileName ("images", ""), 1); // save aehistogram - tpp->writeAEHistogram (getCacheFileName ("aehistograms")); + tpp->writeAEHistogram (getCacheFileName ("aehistograms", "")); // save embedded profile - tpp->writeEmbProfile (getCacheFileName ("embprofiles") + ".icc"); + tpp->writeEmbProfile (getCacheFileName ("embprofiles", ".icc")); // save supplementary data - tpp->writeData (getCacheFileName ("data") + ".txt"); + tpp->writeData (getCacheFileName ("data", ".txt")); } /* @@ -893,13 +879,13 @@ void Thumbnail::updateCache (bool updatePParams, bool updateCacheImageData) if (updatePParams && pparamsValid) { pparams.save ( options.saveParamsFile ? fname + paramFileExtension : "", - options.saveParamsCache ? getCacheFileName ("profiles") + paramFileExtension : "", + options.saveParamsCache ? getCacheFileName ("profiles", paramFileExtension) : "", true ); } if (updateCacheImageData) { - cfs.save (getCacheFileName ("data") + ".txt"); + cfs.save (getCacheFileName ("data", ".txt")); } } @@ -912,10 +898,9 @@ Thumbnail::~Thumbnail () mutex.unlock(); } -Glib::ustring Thumbnail::getCacheFileName (Glib::ustring subdir) +Glib::ustring Thumbnail::getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fext) const { - - return cachemgr->getCacheFileName (subdir, fname, Glib::ustring(), cfs.md5); + return cachemgr->getCacheFileName (subdir, fname, fext, cfs.md5); } void Thumbnail::setFileName (const Glib::ustring fn) @@ -956,7 +941,7 @@ bool Thumbnail::openDefaultViewer(int destination) if (destination == 1) { openFName = Glib::ustring::compose ("%1.%2", BatchQueue::calcAutoFileNameBase(fname), options.saveFormatBatch.format); - if (safe_file_test (openFName, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (openFName, Glib::FILE_TEST_EXISTS)) { wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (openFName.c_str(), -1, NULL, NULL, NULL); ShellExecuteW(NULL, L"open", wfilename, NULL, NULL, SW_SHOWMAXIMIZED ); g_free(wfilename); @@ -970,7 +955,7 @@ bool Thumbnail::openDefaultViewer(int destination) printf("Opening %s\n", openFName.c_str()); - if (safe_file_test (openFName, Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (openFName, Glib::FILE_TEST_EXISTS)) { // Output file exists, so open explorer and select output file wchar_t* org = (wchar_t*)g_utf8_to_utf16 (Glib::ustring::compose("/select,\"%1\"", openFName).c_str(), -1, NULL, NULL, NULL); wchar_t* par = new wchar_t[wcslen(org) + 1]; @@ -991,7 +976,7 @@ bool Thumbnail::openDefaultViewer(int destination) delete[] par; g_free(org); - } else if (safe_file_test (Glib::path_get_dirname(openFName), Glib::FILE_TEST_EXISTS)) { + } else if (Glib::file_test (Glib::path_get_dirname(openFName), Glib::FILE_TEST_EXISTS)) { // Out file does not exist, but directory wchar_t *wfilename = (wchar_t*)g_utf8_to_utf16 (Glib::path_get_dirname(openFName).c_str(), -1, NULL, NULL, NULL); ShellExecuteW(NULL, L"explore", wfilename, NULL, NULL, SW_SHOWNORMAL ); diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index df3b4549e..8656543f0 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -75,7 +75,7 @@ class Thumbnail void loadThumbnail (bool firstTrial = true); void generateExifDateTimeStrings (); - Glib::ustring getCacheFileName (Glib::ustring subdir); + Glib::ustring getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fext) const; public: Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf); diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index 4af9de9d0..5ab4f14ea 100644 --- a/rtgui/whitebalance.cc +++ b/rtgui/whitebalance.cc @@ -17,10 +17,11 @@ * along with RawTherapee. If not, see . */ #include "whitebalance.h" + #include + #include "rtimage.h" #include "options.h" -#include "../rtengine/safegtk.h" #define MINTEMP 1500 //1200 #define MAXTEMP 60000 //12000 @@ -42,19 +43,19 @@ Glib::RefPtr WhiteBalance::wbCameraPB, WhiteBalance::wbAutoPB, Whit void WhiteBalance::init () { - wbPixbufs[WBT_CAMERA] = safe_create_from_file("wb-camera.png"); - wbPixbufs[WBT_AUTO] = safe_create_from_file("wb-auto.png"); - wbPixbufs[WBT_DAYLIGHT] = safe_create_from_file("wb-sun.png"); - wbPixbufs[WBT_CLOUDY] = safe_create_from_file("wb-cloudy.png"); - wbPixbufs[WBT_SHADE] = safe_create_from_file("wb-shade.png"); - wbPixbufs[WBT_WATER] = safe_create_from_file("wb-water.png"); -// wbPixbufs[WBT_WATER2] = safe_create_from_file("wb-water.png"); - wbPixbufs[WBT_TUNGSTEN] = safe_create_from_file("wb-tungsten.png"); - wbPixbufs[WBT_FLUORESCENT] = safe_create_from_file("wb-fluorescent.png"); - wbPixbufs[WBT_LAMP] = safe_create_from_file("wb-lamp.png"); - wbPixbufs[WBT_FLASH] = safe_create_from_file("wb-flash.png"); - wbPixbufs[WBT_LED] = safe_create_from_file("wb-led.png"); - wbPixbufs[WBT_CUSTOM] = safe_create_from_file("wb-custom.png"); + wbPixbufs[WBT_CAMERA] = RTImage::createFromFile ("wb-camera.png"); + wbPixbufs[WBT_AUTO] = RTImage::createFromFile ("wb-auto.png"); + wbPixbufs[WBT_DAYLIGHT] = RTImage::createFromFile ("wb-sun.png"); + wbPixbufs[WBT_CLOUDY] = RTImage::createFromFile ("wb-cloudy.png"); + wbPixbufs[WBT_SHADE] = RTImage::createFromFile ("wb-shade.png"); + wbPixbufs[WBT_WATER] = RTImage::createFromFile ("wb-water.png"); +// wbPixbufs[WBT_WATER2] = RTImage::createFromFile ("wb-water.png"); + wbPixbufs[WBT_TUNGSTEN] = RTImage::createFromFile ("wb-tungsten.png"); + wbPixbufs[WBT_FLUORESCENT] = RTImage::createFromFile ("wb-fluorescent.png"); + wbPixbufs[WBT_LAMP] = RTImage::createFromFile ("wb-lamp.png"); + wbPixbufs[WBT_FLASH] = RTImage::createFromFile ("wb-flash.png"); + wbPixbufs[WBT_LED] = RTImage::createFromFile ("wb-led.png"); + wbPixbufs[WBT_CUSTOM] = RTImage::createFromFile ("wb-custom.png"); } void WhiteBalance::cleanup () diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index ccf1e621b..84fae9032 100644 --- a/rtgui/xtransrawexposure.cc +++ b/rtgui/xtransrawexposure.cc @@ -18,7 +18,6 @@ */ #include "xtransrawexposure.h" #include "guiutils.h" -#include "../rtengine/safegtk.h" #include using namespace rtengine; diff --git a/tools/win/InnoSetup/WindowsInnoSetup.iss.in b/tools/win/InnoSetup/WindowsInnoSetup.iss.in index 42f2a0feb..5c4a2a239 100644 --- a/tools/win/InnoSetup/WindowsInnoSetup.iss.in +++ b/tools/win/InnoSetup/WindowsInnoSetup.iss.in @@ -55,7 +55,7 @@ LicenseFile={#MyBuildBasePath}\LICENSE.txt OutputDir={#MyBuildBasePath}\..\ OutputBaseFilename={#MyAppName}_{#MySystemName}_{#MyBitDepth}_{#MyAppFullVersion} SetupIconFile={#MySourceBasePath}\rtgui\RT.ico -WizardImageFile={#MySourceBasePath}\rtdata\win\InnoSetup\installerStrip.bmp +WizardImageFile={#MySourceBasePath}\tools\win\InnoSetup\installerStrip.bmp WizardImageBackColor=$2A2A2A Compression=lzma SolidCompression=yes @@ -117,7 +117,7 @@ Source: "{#MyBuildBasePath}\options"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\*.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\gspawn-win{#MyBitDepth}-helper.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\gspawn-win{#MyBitDepth}-helper-console.exe"; DestDir: "{app}"; Flags: ignoreversion - +;Source: "{#MyBuildBasePath}\gdb.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\fonts\DroidSansMonoSlashed.ttf"; DestDir: "{fonts}"; FontInstall: "Droid Sans Mono Slashed"; Flags: onlyifdoesntexist uninsneveruninstall ; NOTE: Don't use "Flags: ignoreversion" on any shared system files